17ac6653aSJeff Kirsher /*******************************************************************************
27ac6653aSJeff Kirsher   This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
37ac6653aSJeff Kirsher   ST Ethernet IPs are built around a Synopsys IP Core.
47ac6653aSJeff Kirsher 
5286a8372SGiuseppe CAVALLARO 	Copyright(C) 2007-2011 STMicroelectronics Ltd
67ac6653aSJeff Kirsher 
77ac6653aSJeff Kirsher   This program is free software; you can redistribute it and/or modify it
87ac6653aSJeff Kirsher   under the terms and conditions of the GNU General Public License,
97ac6653aSJeff Kirsher   version 2, as published by the Free Software Foundation.
107ac6653aSJeff Kirsher 
117ac6653aSJeff Kirsher   This program is distributed in the hope it will be useful, but WITHOUT
127ac6653aSJeff Kirsher   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
137ac6653aSJeff Kirsher   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
147ac6653aSJeff Kirsher   more details.
157ac6653aSJeff Kirsher 
167ac6653aSJeff Kirsher   You should have received a copy of the GNU General Public License along with
177ac6653aSJeff Kirsher   this program; if not, write to the Free Software Foundation, Inc.,
187ac6653aSJeff Kirsher   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
197ac6653aSJeff Kirsher 
207ac6653aSJeff Kirsher   The full GNU General Public License is included in this distribution in
217ac6653aSJeff Kirsher   the file called "COPYING".
227ac6653aSJeff Kirsher 
237ac6653aSJeff Kirsher   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
247ac6653aSJeff Kirsher 
257ac6653aSJeff Kirsher   Documentation available at:
267ac6653aSJeff Kirsher 	http://www.stlinux.com
277ac6653aSJeff Kirsher   Support available at:
287ac6653aSJeff Kirsher 	https://bugzilla.stlinux.com/
297ac6653aSJeff Kirsher *******************************************************************************/
307ac6653aSJeff Kirsher 
316a81c26fSViresh Kumar #include <linux/clk.h>
327ac6653aSJeff Kirsher #include <linux/kernel.h>
337ac6653aSJeff Kirsher #include <linux/interrupt.h>
347ac6653aSJeff Kirsher #include <linux/ip.h>
357ac6653aSJeff Kirsher #include <linux/tcp.h>
367ac6653aSJeff Kirsher #include <linux/skbuff.h>
377ac6653aSJeff Kirsher #include <linux/ethtool.h>
387ac6653aSJeff Kirsher #include <linux/if_ether.h>
397ac6653aSJeff Kirsher #include <linux/crc32.h>
407ac6653aSJeff Kirsher #include <linux/mii.h>
4101789349SJiri Pirko #include <linux/if.h>
427ac6653aSJeff Kirsher #include <linux/if_vlan.h>
437ac6653aSJeff Kirsher #include <linux/dma-mapping.h>
447ac6653aSJeff Kirsher #include <linux/slab.h>
457ac6653aSJeff Kirsher #include <linux/prefetch.h>
46db88f10aSSrinivas Kandagatla #include <linux/pinctrl/consumer.h>
4750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
487ac29055SGiuseppe CAVALLARO #include <linux/debugfs.h>
497ac29055SGiuseppe CAVALLARO #include <linux/seq_file.h>
5050fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
51891434b1SRayagond Kokatanur #include <linux/net_tstamp.h>
52891434b1SRayagond Kokatanur #include "stmmac_ptp.h"
53286a8372SGiuseppe CAVALLARO #include "stmmac.h"
54c5e4ddbdSChen-Yu Tsai #include <linux/reset.h>
557ac6653aSJeff Kirsher 
567ac6653aSJeff Kirsher #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
577ac6653aSJeff Kirsher 
587ac6653aSJeff Kirsher /* Module parameters */
5932ceabcaSGiuseppe CAVALLARO #define TX_TIMEO	5000
607ac6653aSJeff Kirsher static int watchdog = TX_TIMEO;
617ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR);
6232ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)");
637ac6653aSJeff Kirsher 
6432ceabcaSGiuseppe CAVALLARO static int debug = -1;
657ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR);
6632ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
677ac6653aSJeff Kirsher 
6847d1f71fSstephen hemminger static int phyaddr = -1;
697ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO);
707ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address");
717ac6653aSJeff Kirsher 
727ac6653aSJeff Kirsher #define DMA_TX_SIZE 256
737ac6653aSJeff Kirsher static int dma_txsize = DMA_TX_SIZE;
747ac6653aSJeff Kirsher module_param(dma_txsize, int, S_IRUGO | S_IWUSR);
757ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_txsize, "Number of descriptors in the TX list");
767ac6653aSJeff Kirsher 
777ac6653aSJeff Kirsher #define DMA_RX_SIZE 256
787ac6653aSJeff Kirsher static int dma_rxsize = DMA_RX_SIZE;
797ac6653aSJeff Kirsher module_param(dma_rxsize, int, S_IRUGO | S_IWUSR);
807ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_rxsize, "Number of descriptors in the RX list");
817ac6653aSJeff Kirsher 
827ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF;
837ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR);
847ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]");
857ac6653aSJeff Kirsher 
867ac6653aSJeff Kirsher static int pause = PAUSE_TIME;
877ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR);
887ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time");
897ac6653aSJeff Kirsher 
907ac6653aSJeff Kirsher #define TC_DEFAULT 64
917ac6653aSJeff Kirsher static int tc = TC_DEFAULT;
927ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR);
937ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value");
947ac6653aSJeff Kirsher 
95d916701cSGiuseppe CAVALLARO #define	DEFAULT_BUFSIZE	1536
96d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE;
977ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR);
987ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size");
997ac6653aSJeff Kirsher 
1007ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
1017ac6653aSJeff Kirsher 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
1027ac6653aSJeff Kirsher 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
1037ac6653aSJeff Kirsher 
104d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER	1000
105d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
106d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR);
107d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
108f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
109d765955dSGiuseppe CAVALLARO 
1104a7d666aSGiuseppe CAVALLARO /* By default the driver will use the ring mode to manage tx and rx descriptors
1114a7d666aSGiuseppe CAVALLARO  * but passing this value so user can force to use the chain instead of the ring
1124a7d666aSGiuseppe CAVALLARO  */
1134a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode;
1144a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO);
1154a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
1164a7d666aSGiuseppe CAVALLARO 
1177ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
1187ac6653aSJeff Kirsher 
11950fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
120bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev);
121bfab27a1SGiuseppe CAVALLARO static void stmmac_exit_fs(void);
122bfab27a1SGiuseppe CAVALLARO #endif
123bfab27a1SGiuseppe CAVALLARO 
1249125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
1259125cdd1SGiuseppe CAVALLARO 
1267ac6653aSJeff Kirsher /**
1277ac6653aSJeff Kirsher  * stmmac_verify_args - verify the driver parameters.
128732fdf0eSGiuseppe CAVALLARO  * Description: it checks the driver parameters and set a default in case of
129732fdf0eSGiuseppe CAVALLARO  * errors.
1307ac6653aSJeff Kirsher  */
1317ac6653aSJeff Kirsher static void stmmac_verify_args(void)
1327ac6653aSJeff Kirsher {
1337ac6653aSJeff Kirsher 	if (unlikely(watchdog < 0))
1347ac6653aSJeff Kirsher 		watchdog = TX_TIMEO;
1357ac6653aSJeff Kirsher 	if (unlikely(dma_rxsize < 0))
1367ac6653aSJeff Kirsher 		dma_rxsize = DMA_RX_SIZE;
1377ac6653aSJeff Kirsher 	if (unlikely(dma_txsize < 0))
1387ac6653aSJeff Kirsher 		dma_txsize = DMA_TX_SIZE;
139d916701cSGiuseppe CAVALLARO 	if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
140d916701cSGiuseppe CAVALLARO 		buf_sz = DEFAULT_BUFSIZE;
1417ac6653aSJeff Kirsher 	if (unlikely(flow_ctrl > 1))
1427ac6653aSJeff Kirsher 		flow_ctrl = FLOW_AUTO;
1437ac6653aSJeff Kirsher 	else if (likely(flow_ctrl < 0))
1447ac6653aSJeff Kirsher 		flow_ctrl = FLOW_OFF;
1457ac6653aSJeff Kirsher 	if (unlikely((pause < 0) || (pause > 0xffff)))
1467ac6653aSJeff Kirsher 		pause = PAUSE_TIME;
147d765955dSGiuseppe CAVALLARO 	if (eee_timer < 0)
148d765955dSGiuseppe CAVALLARO 		eee_timer = STMMAC_DEFAULT_LPI_TIMER;
1497ac6653aSJeff Kirsher }
1507ac6653aSJeff Kirsher 
15132ceabcaSGiuseppe CAVALLARO /**
15232ceabcaSGiuseppe CAVALLARO  * stmmac_clk_csr_set - dynamically set the MDC clock
15332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15432ceabcaSGiuseppe CAVALLARO  * Description: this is to dynamically set the MDC clock according to the csr
15532ceabcaSGiuseppe CAVALLARO  * clock input.
15632ceabcaSGiuseppe CAVALLARO  * Note:
15732ceabcaSGiuseppe CAVALLARO  *	If a specific clk_csr value is passed from the platform
15832ceabcaSGiuseppe CAVALLARO  *	this means that the CSR Clock Range selection cannot be
15932ceabcaSGiuseppe CAVALLARO  *	changed at run-time and it is fixed (as reported in the driver
16032ceabcaSGiuseppe CAVALLARO  *	documentation). Viceversa the driver will try to set the MDC
16132ceabcaSGiuseppe CAVALLARO  *	clock dynamically according to the actual clock input.
16232ceabcaSGiuseppe CAVALLARO  */
163cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv)
164cd7201f4SGiuseppe CAVALLARO {
165cd7201f4SGiuseppe CAVALLARO 	u32 clk_rate;
166cd7201f4SGiuseppe CAVALLARO 
167cd7201f4SGiuseppe CAVALLARO 	clk_rate = clk_get_rate(priv->stmmac_clk);
168cd7201f4SGiuseppe CAVALLARO 
169cd7201f4SGiuseppe CAVALLARO 	/* Platform provided default clk_csr would be assumed valid
170ceb69499SGiuseppe CAVALLARO 	 * for all other cases except for the below mentioned ones.
171ceb69499SGiuseppe CAVALLARO 	 * For values higher than the IEEE 802.3 specified frequency
172ceb69499SGiuseppe CAVALLARO 	 * we can not estimate the proper divider as it is not known
173ceb69499SGiuseppe CAVALLARO 	 * the frequency of clk_csr_i. So we do not change the default
174ceb69499SGiuseppe CAVALLARO 	 * divider.
175ceb69499SGiuseppe CAVALLARO 	 */
176cd7201f4SGiuseppe CAVALLARO 	if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
177cd7201f4SGiuseppe CAVALLARO 		if (clk_rate < CSR_F_35M)
178cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_20_35M;
179cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
180cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_35_60M;
181cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
182cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_60_100M;
183cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
184cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_100_150M;
185cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
186cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_150_250M;
187cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
188cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_250_300M;
189ceb69499SGiuseppe CAVALLARO 	}
190cd7201f4SGiuseppe CAVALLARO }
191cd7201f4SGiuseppe CAVALLARO 
1927ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len)
1937ac6653aSJeff Kirsher {
194424c4f78SAndy Shevchenko 	pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf);
195424c4f78SAndy Shevchenko 	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
1967ac6653aSJeff Kirsher }
1977ac6653aSJeff Kirsher 
1987ac6653aSJeff Kirsher /* minimum number of free TX descriptors required to wake up TX process */
1997ac6653aSJeff Kirsher #define STMMAC_TX_THRESH(x)	(x->dma_tx_size/4)
2007ac6653aSJeff Kirsher 
2017ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
2027ac6653aSJeff Kirsher {
2037ac6653aSJeff Kirsher 	return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
2047ac6653aSJeff Kirsher }
2057ac6653aSJeff Kirsher 
20632ceabcaSGiuseppe CAVALLARO /**
207732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed - callback for speed selection
20832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
20932ceabcaSGiuseppe CAVALLARO  * Description: on some platforms (e.g. ST), some HW system configuraton
21032ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2117ac6653aSJeff Kirsher  */
2127ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2137ac6653aSJeff Kirsher {
2147ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
2157ac6653aSJeff Kirsher 
2167ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
217ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2187ac6653aSJeff Kirsher }
2197ac6653aSJeff Kirsher 
22032ceabcaSGiuseppe CAVALLARO /**
221732fdf0eSGiuseppe CAVALLARO  * stmmac_enable_eee_mode - check and enter in LPI mode
22232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
223732fdf0eSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode in case of
224732fdf0eSGiuseppe CAVALLARO  * EEE.
22532ceabcaSGiuseppe CAVALLARO  */
226d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
227d765955dSGiuseppe CAVALLARO {
228d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
229d765955dSGiuseppe CAVALLARO 	if ((priv->dirty_tx == priv->cur_tx) &&
230d765955dSGiuseppe CAVALLARO 	    (priv->tx_path_in_lpi_mode == false))
2317ed24bbeSVince Bridgers 		priv->hw->mac->set_eee_mode(priv->hw);
232d765955dSGiuseppe CAVALLARO }
233d765955dSGiuseppe CAVALLARO 
23432ceabcaSGiuseppe CAVALLARO /**
235732fdf0eSGiuseppe CAVALLARO  * stmmac_disable_eee_mode - disable and exit from LPI mode
23632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
23732ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
23832ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
23932ceabcaSGiuseppe CAVALLARO  */
240d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
241d765955dSGiuseppe CAVALLARO {
2427ed24bbeSVince Bridgers 	priv->hw->mac->reset_eee_mode(priv->hw);
243d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
244d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
245d765955dSGiuseppe CAVALLARO }
246d765955dSGiuseppe CAVALLARO 
247d765955dSGiuseppe CAVALLARO /**
248732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer - EEE TX SW timer.
249d765955dSGiuseppe CAVALLARO  * @arg : data hook
250d765955dSGiuseppe CAVALLARO  * Description:
25132ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
252d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
253d765955dSGiuseppe CAVALLARO  */
254d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
255d765955dSGiuseppe CAVALLARO {
256d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
257d765955dSGiuseppe CAVALLARO 
258d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
259f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
260d765955dSGiuseppe CAVALLARO }
261d765955dSGiuseppe CAVALLARO 
262d765955dSGiuseppe CAVALLARO /**
263732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_init - init EEE
26432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
265d765955dSGiuseppe CAVALLARO  * Description:
266732fdf0eSGiuseppe CAVALLARO  *  if the GMAC supports the EEE (from the HW cap reg) and the phy device
267732fdf0eSGiuseppe CAVALLARO  *  can also manage EEE, this function enable the LPI state and start related
268732fdf0eSGiuseppe CAVALLARO  *  timer.
269d765955dSGiuseppe CAVALLARO  */
270d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
271d765955dSGiuseppe CAVALLARO {
27256b88c25SGiuseppe CAVALLARO 	char *phy_bus_name = priv->plat->phy_bus_name;
2734741cf9cSGiuseppe CAVALLARO 	unsigned long flags;
274d765955dSGiuseppe CAVALLARO 	bool ret = false;
275d765955dSGiuseppe CAVALLARO 
276f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
277f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
278f5351ef7SGiuseppe CAVALLARO 	 */
279f5351ef7SGiuseppe CAVALLARO 	if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
280f5351ef7SGiuseppe CAVALLARO 	    (priv->pcs == STMMAC_PCS_RTBI))
281f5351ef7SGiuseppe CAVALLARO 		goto out;
282f5351ef7SGiuseppe CAVALLARO 
28356b88c25SGiuseppe CAVALLARO 	/* Never init EEE in case of a switch is attached */
28456b88c25SGiuseppe CAVALLARO 	if (phy_bus_name && (!strcmp(phy_bus_name, "fixed")))
28556b88c25SGiuseppe CAVALLARO 		goto out;
28656b88c25SGiuseppe CAVALLARO 
287d765955dSGiuseppe CAVALLARO 	/* MAC core supports the EEE feature. */
288d765955dSGiuseppe CAVALLARO 	if (priv->dma_cap.eee) {
28983bf79b6SGiuseppe CAVALLARO 		int tx_lpi_timer = priv->tx_lpi_timer;
290d765955dSGiuseppe CAVALLARO 
29183bf79b6SGiuseppe CAVALLARO 		/* Check if the PHY supports EEE */
29283bf79b6SGiuseppe CAVALLARO 		if (phy_init_eee(priv->phydev, 1)) {
29383bf79b6SGiuseppe CAVALLARO 			/* To manage at run-time if the EEE cannot be supported
29483bf79b6SGiuseppe CAVALLARO 			 * anymore (for example because the lp caps have been
29583bf79b6SGiuseppe CAVALLARO 			 * changed).
29683bf79b6SGiuseppe CAVALLARO 			 * In that case the driver disable own timers.
29783bf79b6SGiuseppe CAVALLARO 			 */
2984741cf9cSGiuseppe CAVALLARO 			spin_lock_irqsave(&priv->lock, flags);
29983bf79b6SGiuseppe CAVALLARO 			if (priv->eee_active) {
30083bf79b6SGiuseppe CAVALLARO 				pr_debug("stmmac: disable EEE\n");
30183bf79b6SGiuseppe CAVALLARO 				del_timer_sync(&priv->eee_ctrl_timer);
3027ed24bbeSVince Bridgers 				priv->hw->mac->set_eee_timer(priv->hw, 0,
30383bf79b6SGiuseppe CAVALLARO 							     tx_lpi_timer);
30483bf79b6SGiuseppe CAVALLARO 			}
30583bf79b6SGiuseppe CAVALLARO 			priv->eee_active = 0;
3064741cf9cSGiuseppe CAVALLARO 			spin_unlock_irqrestore(&priv->lock, flags);
30783bf79b6SGiuseppe CAVALLARO 			goto out;
30883bf79b6SGiuseppe CAVALLARO 		}
30983bf79b6SGiuseppe CAVALLARO 		/* Activate the EEE and start timers */
3104741cf9cSGiuseppe CAVALLARO 		spin_lock_irqsave(&priv->lock, flags);
311f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
312d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
313d765955dSGiuseppe CAVALLARO 			init_timer(&priv->eee_ctrl_timer);
314d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
315d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.data = (unsigned long)priv;
316f5351ef7SGiuseppe CAVALLARO 			priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
317d765955dSGiuseppe CAVALLARO 			add_timer(&priv->eee_ctrl_timer);
318d765955dSGiuseppe CAVALLARO 
3197ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_timer(priv->hw,
320f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
32183bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
32271965352SGiuseppe CAVALLARO 		}
323f5351ef7SGiuseppe CAVALLARO 		/* Set HW EEE according to the speed */
32471965352SGiuseppe CAVALLARO 		priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
325d765955dSGiuseppe CAVALLARO 
326d765955dSGiuseppe CAVALLARO 		ret = true;
3274741cf9cSGiuseppe CAVALLARO 		spin_unlock_irqrestore(&priv->lock, flags);
3284741cf9cSGiuseppe CAVALLARO 
3294741cf9cSGiuseppe CAVALLARO 		pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
330d765955dSGiuseppe CAVALLARO 	}
331d765955dSGiuseppe CAVALLARO out:
332d765955dSGiuseppe CAVALLARO 	return ret;
333d765955dSGiuseppe CAVALLARO }
334d765955dSGiuseppe CAVALLARO 
335732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps
33632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
337891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
338891434b1SRayagond Kokatanur  * @skb : the socket buffer
339891434b1SRayagond Kokatanur  * Description :
340891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
341891434b1SRayagond Kokatanur  * and also perform some sanity checks.
342891434b1SRayagond Kokatanur  */
343891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
344ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
345891434b1SRayagond Kokatanur {
346891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
347891434b1SRayagond Kokatanur 	u64 ns;
348891434b1SRayagond Kokatanur 	void *desc = NULL;
349891434b1SRayagond Kokatanur 
350891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
351891434b1SRayagond Kokatanur 		return;
352891434b1SRayagond Kokatanur 
353ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
35475e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
355891434b1SRayagond Kokatanur 		return;
356891434b1SRayagond Kokatanur 
357891434b1SRayagond Kokatanur 	if (priv->adv_ts)
358891434b1SRayagond Kokatanur 		desc = (priv->dma_etx + entry);
359891434b1SRayagond Kokatanur 	else
360891434b1SRayagond Kokatanur 		desc = (priv->dma_tx + entry);
361891434b1SRayagond Kokatanur 
362891434b1SRayagond Kokatanur 	/* check tx tstamp status */
363891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
364891434b1SRayagond Kokatanur 		return;
365891434b1SRayagond Kokatanur 
366891434b1SRayagond Kokatanur 	/* get the valid tstamp */
367891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
368891434b1SRayagond Kokatanur 
369891434b1SRayagond Kokatanur 	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
370891434b1SRayagond Kokatanur 	shhwtstamp.hwtstamp = ns_to_ktime(ns);
371891434b1SRayagond Kokatanur 	/* pass tstamp to stack */
372891434b1SRayagond Kokatanur 	skb_tstamp_tx(skb, &shhwtstamp);
373891434b1SRayagond Kokatanur 
374891434b1SRayagond Kokatanur 	return;
375891434b1SRayagond Kokatanur }
376891434b1SRayagond Kokatanur 
377732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps
37832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
379891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
380891434b1SRayagond Kokatanur  * @skb : the socket buffer
381891434b1SRayagond Kokatanur  * Description :
382891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
383891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
384891434b1SRayagond Kokatanur  */
385891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
386ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
387891434b1SRayagond Kokatanur {
388891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
389891434b1SRayagond Kokatanur 	u64 ns;
390891434b1SRayagond Kokatanur 	void *desc = NULL;
391891434b1SRayagond Kokatanur 
392891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
393891434b1SRayagond Kokatanur 		return;
394891434b1SRayagond Kokatanur 
395891434b1SRayagond Kokatanur 	if (priv->adv_ts)
396891434b1SRayagond Kokatanur 		desc = (priv->dma_erx + entry);
397891434b1SRayagond Kokatanur 	else
398891434b1SRayagond Kokatanur 		desc = (priv->dma_rx + entry);
399891434b1SRayagond Kokatanur 
400ceb69499SGiuseppe CAVALLARO 	/* exit if rx tstamp is not valid */
401891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
402891434b1SRayagond Kokatanur 		return;
403891434b1SRayagond Kokatanur 
404891434b1SRayagond Kokatanur 	/* get valid tstamp */
405891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
406891434b1SRayagond Kokatanur 	shhwtstamp = skb_hwtstamps(skb);
407891434b1SRayagond Kokatanur 	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
408891434b1SRayagond Kokatanur 	shhwtstamp->hwtstamp = ns_to_ktime(ns);
409891434b1SRayagond Kokatanur }
410891434b1SRayagond Kokatanur 
411891434b1SRayagond Kokatanur /**
412891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
413891434b1SRayagond Kokatanur  *  @dev: device pointer.
414891434b1SRayagond Kokatanur  *  @ifr: An IOCTL specefic structure, that can contain a pointer to
415891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
416891434b1SRayagond Kokatanur  *  Description:
417891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
418891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
419891434b1SRayagond Kokatanur  *  Return Value:
420891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
421891434b1SRayagond Kokatanur  */
422891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
423891434b1SRayagond Kokatanur {
424891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
425891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
426891434b1SRayagond Kokatanur 	struct timespec now;
427891434b1SRayagond Kokatanur 	u64 temp = 0;
428891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
429891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
430891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
431891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
432891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
433891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
434891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
435891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
436891434b1SRayagond Kokatanur 	u32 value = 0;
437891434b1SRayagond Kokatanur 
438891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
439891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
440891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
441891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
442891434b1SRayagond Kokatanur 
443891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
444891434b1SRayagond Kokatanur 	}
445891434b1SRayagond Kokatanur 
446891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
447891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
448891434b1SRayagond Kokatanur 		return -EFAULT;
449891434b1SRayagond Kokatanur 
450891434b1SRayagond Kokatanur 	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
451891434b1SRayagond Kokatanur 		 __func__, config.flags, config.tx_type, config.rx_filter);
452891434b1SRayagond Kokatanur 
453891434b1SRayagond Kokatanur 	/* reserved for future extensions */
454891434b1SRayagond Kokatanur 	if (config.flags)
455891434b1SRayagond Kokatanur 		return -EINVAL;
456891434b1SRayagond Kokatanur 
4575f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4585f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
459891434b1SRayagond Kokatanur 		return -ERANGE;
460891434b1SRayagond Kokatanur 
461891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
462891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
463891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
464ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
465891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
466891434b1SRayagond Kokatanur 			break;
467891434b1SRayagond Kokatanur 
468891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
469ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
470891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
471891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
472891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
473891434b1SRayagond Kokatanur 
474891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
475891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
476891434b1SRayagond Kokatanur 			break;
477891434b1SRayagond Kokatanur 
478891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
479ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
480891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
481891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
482891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
483891434b1SRayagond Kokatanur 
484891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
485891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
486891434b1SRayagond Kokatanur 			break;
487891434b1SRayagond Kokatanur 
488891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
489ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
490891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
491891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
492891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
493891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
494891434b1SRayagond Kokatanur 
495891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
496891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
497891434b1SRayagond Kokatanur 			break;
498891434b1SRayagond Kokatanur 
499891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
500ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
501891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
502891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
503891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
504891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
505891434b1SRayagond Kokatanur 
506891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
507891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
508891434b1SRayagond Kokatanur 			break;
509891434b1SRayagond Kokatanur 
510891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
511ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
512891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
513891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
514891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
515891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
516891434b1SRayagond Kokatanur 
517891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
518891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
519891434b1SRayagond Kokatanur 			break;
520891434b1SRayagond Kokatanur 
521891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
522ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
523891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
524891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
525891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
526891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
527891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
528891434b1SRayagond Kokatanur 
529891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
530891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
531891434b1SRayagond Kokatanur 			break;
532891434b1SRayagond Kokatanur 
533891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
534ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
535891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
536891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
537891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
538891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
539891434b1SRayagond Kokatanur 
540891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
541891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
542891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
543891434b1SRayagond Kokatanur 			break;
544891434b1SRayagond Kokatanur 
545891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
546ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
547891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
548891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
549891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
550891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
551891434b1SRayagond Kokatanur 
552891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
553891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
554891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
555891434b1SRayagond Kokatanur 			break;
556891434b1SRayagond Kokatanur 
557891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
558ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
559891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
560891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
561891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
562891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
563891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
564891434b1SRayagond Kokatanur 
565891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
566891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
567891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
568891434b1SRayagond Kokatanur 			break;
569891434b1SRayagond Kokatanur 
570891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
571ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
572891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
573891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
574891434b1SRayagond Kokatanur 			break;
575891434b1SRayagond Kokatanur 
576891434b1SRayagond Kokatanur 		default:
577891434b1SRayagond Kokatanur 			return -ERANGE;
578891434b1SRayagond Kokatanur 		}
579891434b1SRayagond Kokatanur 	} else {
580891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
581891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
582891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
583891434b1SRayagond Kokatanur 			break;
584891434b1SRayagond Kokatanur 		default:
585891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
586891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
587891434b1SRayagond Kokatanur 			break;
588891434b1SRayagond Kokatanur 		}
589891434b1SRayagond Kokatanur 	}
590891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
5915f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
592891434b1SRayagond Kokatanur 
593891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
594891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
595891434b1SRayagond Kokatanur 	else {
596891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
597891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
598891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
599891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
600891434b1SRayagond Kokatanur 
601891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
602891434b1SRayagond Kokatanur 
603891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
604891434b1SRayagond Kokatanur 		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
605891434b1SRayagond Kokatanur 
606891434b1SRayagond Kokatanur 		/* calculate default added value:
607891434b1SRayagond Kokatanur 		 * formula is :
608891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
6095566401fSGiuseppe CAVALLARO 		 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
6105566401fSGiuseppe CAVALLARO 		 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
6115566401fSGiuseppe CAVALLARO 		 * NOTE: clk_ptp_ref_i should be >= 50MHz to
612891434b1SRayagond Kokatanur 		 *       achive 20ns accuracy.
613891434b1SRayagond Kokatanur 		 *
614891434b1SRayagond Kokatanur 		 * 2^x * y == (y << x), hence
615891434b1SRayagond Kokatanur 		 * 2^32 * 50000000 ==> (50000000 << 32)
616891434b1SRayagond Kokatanur 		 */
617891434b1SRayagond Kokatanur 		temp = (u64) (50000000ULL << 32);
6185566401fSGiuseppe CAVALLARO 		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
619891434b1SRayagond Kokatanur 		priv->hw->ptp->config_addend(priv->ioaddr,
620891434b1SRayagond Kokatanur 					     priv->default_addend);
621891434b1SRayagond Kokatanur 
622891434b1SRayagond Kokatanur 		/* initialize system time */
623891434b1SRayagond Kokatanur 		getnstimeofday(&now);
624891434b1SRayagond Kokatanur 		priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
625891434b1SRayagond Kokatanur 					    now.tv_nsec);
626891434b1SRayagond Kokatanur 	}
627891434b1SRayagond Kokatanur 
628891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
629891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
630891434b1SRayagond Kokatanur }
631891434b1SRayagond Kokatanur 
63232ceabcaSGiuseppe CAVALLARO /**
633732fdf0eSGiuseppe CAVALLARO  * stmmac_init_ptp - init PTP
63432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
635732fdf0eSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or PTPv2.
63632ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
637732fdf0eSGiuseppe CAVALLARO  * This function also registers the ptp driver.
63832ceabcaSGiuseppe CAVALLARO  */
63992ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
640891434b1SRayagond Kokatanur {
64192ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
64292ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
64392ba6888SRayagond Kokatanur 
6445566401fSGiuseppe CAVALLARO 	/* Fall-back to main clock in case of no PTP ref is passed */
6455566401fSGiuseppe CAVALLARO 	priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
6465566401fSGiuseppe CAVALLARO 	if (IS_ERR(priv->clk_ptp_ref)) {
6475566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
6485566401fSGiuseppe CAVALLARO 		priv->clk_ptp_ref = NULL;
6495566401fSGiuseppe CAVALLARO 	} else {
6505566401fSGiuseppe CAVALLARO 		clk_prepare_enable(priv->clk_ptp_ref);
6515566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
6525566401fSGiuseppe CAVALLARO 	}
6535566401fSGiuseppe CAVALLARO 
654891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6557cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
656891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6577cd01399SVince Bridgers 
6587cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6597cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6607cd01399SVince Bridgers 
6617cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6627cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
663891434b1SRayagond Kokatanur 
664891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
665891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
666891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
66792ba6888SRayagond Kokatanur 
66892ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
66992ba6888SRayagond Kokatanur }
67092ba6888SRayagond Kokatanur 
67192ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
67292ba6888SRayagond Kokatanur {
6735566401fSGiuseppe CAVALLARO 	if (priv->clk_ptp_ref)
6745566401fSGiuseppe CAVALLARO 		clk_disable_unprepare(priv->clk_ptp_ref);
67592ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
676891434b1SRayagond Kokatanur }
677891434b1SRayagond Kokatanur 
6787ac6653aSJeff Kirsher /**
679732fdf0eSGiuseppe CAVALLARO  * stmmac_adjust_link - adjusts the link parameters
6807ac6653aSJeff Kirsher  * @dev: net device structure
681732fdf0eSGiuseppe CAVALLARO  * Description: this is the helper called by the physical abstraction layer
682732fdf0eSGiuseppe CAVALLARO  * drivers to communicate the phy link status. According the speed and duplex
683732fdf0eSGiuseppe CAVALLARO  * this driver can invoke registered glue-logic as well.
684732fdf0eSGiuseppe CAVALLARO  * It also invoke the eee initialization because it could happen when switch
685732fdf0eSGiuseppe CAVALLARO  * on different networks (that are eee capable).
6867ac6653aSJeff Kirsher  */
6877ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6887ac6653aSJeff Kirsher {
6897ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6907ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6917ac6653aSJeff Kirsher 	unsigned long flags;
6927ac6653aSJeff Kirsher 	int new_state = 0;
6937ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6947ac6653aSJeff Kirsher 
6957ac6653aSJeff Kirsher 	if (phydev == NULL)
6967ac6653aSJeff Kirsher 		return;
6977ac6653aSJeff Kirsher 
6987ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
699d765955dSGiuseppe CAVALLARO 
7007ac6653aSJeff Kirsher 	if (phydev->link) {
7017ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
7027ac6653aSJeff Kirsher 
7037ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
7047ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
7057ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
7067ac6653aSJeff Kirsher 			new_state = 1;
7077ac6653aSJeff Kirsher 			if (!(phydev->duplex))
7087ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
7097ac6653aSJeff Kirsher 			else
7107ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
7117ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
7127ac6653aSJeff Kirsher 		}
7137ac6653aSJeff Kirsher 		/* Flow Control operation */
7147ac6653aSJeff Kirsher 		if (phydev->pause)
7157ed24bbeSVince Bridgers 			priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
7167ac6653aSJeff Kirsher 						 fc, pause_time);
7177ac6653aSJeff Kirsher 
7187ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7197ac6653aSJeff Kirsher 			new_state = 1;
7207ac6653aSJeff Kirsher 			switch (phydev->speed) {
7217ac6653aSJeff Kirsher 			case 1000:
7227ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
7237ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7247ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7257ac6653aSJeff Kirsher 				break;
7267ac6653aSJeff Kirsher 			case 100:
7277ac6653aSJeff Kirsher 			case 10:
7287ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
7297ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7307ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
7317ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
7327ac6653aSJeff Kirsher 					} else {
7337ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7347ac6653aSJeff Kirsher 					}
7357ac6653aSJeff Kirsher 				} else {
7367ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7377ac6653aSJeff Kirsher 				}
7387ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7397ac6653aSJeff Kirsher 				break;
7407ac6653aSJeff Kirsher 			default:
7417ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
742ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
743ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7447ac6653aSJeff Kirsher 				break;
7457ac6653aSJeff Kirsher 			}
7467ac6653aSJeff Kirsher 
7477ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7487ac6653aSJeff Kirsher 		}
7497ac6653aSJeff Kirsher 
7507ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7517ac6653aSJeff Kirsher 
7527ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7537ac6653aSJeff Kirsher 			new_state = 1;
7547ac6653aSJeff Kirsher 			priv->oldlink = 1;
7557ac6653aSJeff Kirsher 		}
7567ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7577ac6653aSJeff Kirsher 		new_state = 1;
7587ac6653aSJeff Kirsher 		priv->oldlink = 0;
7597ac6653aSJeff Kirsher 		priv->speed = 0;
7607ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7617ac6653aSJeff Kirsher 	}
7627ac6653aSJeff Kirsher 
7637ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7647ac6653aSJeff Kirsher 		phy_print_status(phydev);
7657ac6653aSJeff Kirsher 
7664741cf9cSGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
7674741cf9cSGiuseppe CAVALLARO 
768f5351ef7SGiuseppe CAVALLARO 	/* At this stage, it could be needed to setup the EEE or adjust some
769f5351ef7SGiuseppe CAVALLARO 	 * MAC related HW registers.
770f5351ef7SGiuseppe CAVALLARO 	 */
771f5351ef7SGiuseppe CAVALLARO 	priv->eee_enabled = stmmac_eee_init(priv);
7727ac6653aSJeff Kirsher }
7737ac6653aSJeff Kirsher 
77432ceabcaSGiuseppe CAVALLARO /**
775732fdf0eSGiuseppe CAVALLARO  * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
77632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
77732ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
77832ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
77932ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
78032ceabcaSGiuseppe CAVALLARO  */
781e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
782e58bb43fSGiuseppe CAVALLARO {
783e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
784e58bb43fSGiuseppe CAVALLARO 
785e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7860d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7870d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7880d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7890d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
790e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
791e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
7920d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
793e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
794e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
795e58bb43fSGiuseppe CAVALLARO 		}
796e58bb43fSGiuseppe CAVALLARO 	}
797e58bb43fSGiuseppe CAVALLARO }
798e58bb43fSGiuseppe CAVALLARO 
7997ac6653aSJeff Kirsher /**
8007ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
8017ac6653aSJeff Kirsher  * @dev: net device structure
8027ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
8037ac6653aSJeff Kirsher  * to the mac driver.
8047ac6653aSJeff Kirsher  *  Return value:
8057ac6653aSJeff Kirsher  *  0 on success
8067ac6653aSJeff Kirsher  */
8077ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
8087ac6653aSJeff Kirsher {
8097ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
8107ac6653aSJeff Kirsher 	struct phy_device *phydev;
811d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
8127ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
81379ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
8149cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
8157ac6653aSJeff Kirsher 	priv->oldlink = 0;
8167ac6653aSJeff Kirsher 	priv->speed = 0;
8177ac6653aSJeff Kirsher 	priv->oldduplex = -1;
8187ac6653aSJeff Kirsher 
819f142af2eSSrinivas Kandagatla 	if (priv->plat->phy_bus_name)
820f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
821f142af2eSSrinivas Kandagatla 			 priv->plat->phy_bus_name, priv->plat->bus_id);
822f142af2eSSrinivas Kandagatla 	else
823f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
824f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
825f142af2eSSrinivas Kandagatla 
826d765955dSGiuseppe CAVALLARO 	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8277ac6653aSJeff Kirsher 		 priv->plat->phy_addr);
828d765955dSGiuseppe CAVALLARO 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
8297ac6653aSJeff Kirsher 
830f9a8f83bSFlorian Fainelli 	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
8317ac6653aSJeff Kirsher 
8327ac6653aSJeff Kirsher 	if (IS_ERR(phydev)) {
8337ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
8347ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8357ac6653aSJeff Kirsher 	}
8367ac6653aSJeff Kirsher 
83779ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
838c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8399cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8409cbadf09SSrinivas Kandagatla 		(max_speed < 1000 && max_speed > 0))
841c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
842c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
84379ee1dc3SSrinivas Kandagatla 
8447ac6653aSJeff Kirsher 	/*
8457ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8467ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8477ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8487ac6653aSJeff Kirsher 	 * device as well.
8497ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8507ac6653aSJeff Kirsher 	 */
8517ac6653aSJeff Kirsher 	if (phydev->phy_id == 0) {
8527ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8537ac6653aSJeff Kirsher 		return -ENODEV;
8547ac6653aSJeff Kirsher 	}
8557ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8567ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8577ac6653aSJeff Kirsher 
8587ac6653aSJeff Kirsher 	priv->phydev = phydev;
8597ac6653aSJeff Kirsher 
8607ac6653aSJeff Kirsher 	return 0;
8617ac6653aSJeff Kirsher }
8627ac6653aSJeff Kirsher 
8637ac6653aSJeff Kirsher /**
864732fdf0eSGiuseppe CAVALLARO  * stmmac_display_ring - display ring
86532ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8667ac6653aSJeff Kirsher  * @size: size of the ring.
86732ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
868c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8697ac6653aSJeff Kirsher  */
870c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8717ac6653aSJeff Kirsher {
8727ac6653aSJeff Kirsher 	int i;
873c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
874c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
875c24602efSGiuseppe CAVALLARO 
8767ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
877c24602efSGiuseppe CAVALLARO 		u64 x;
878c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
879c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
880c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
881c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
882c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
883c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
884c24602efSGiuseppe CAVALLARO 			ep++;
885c24602efSGiuseppe CAVALLARO 		} else {
886c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
887c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
888c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
889c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
890c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
891c24602efSGiuseppe CAVALLARO 			p++;
892c24602efSGiuseppe CAVALLARO 		}
8937ac6653aSJeff Kirsher 		pr_info("\n");
8947ac6653aSJeff Kirsher 	}
8957ac6653aSJeff Kirsher }
8967ac6653aSJeff Kirsher 
897c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
898c24602efSGiuseppe CAVALLARO {
899c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
900c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
901c24602efSGiuseppe CAVALLARO 
902c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
903c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
904c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
905c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
906c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
907c24602efSGiuseppe CAVALLARO 	} else {
908c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
909c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
910c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
911c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
912c24602efSGiuseppe CAVALLARO 	}
913c24602efSGiuseppe CAVALLARO }
914c24602efSGiuseppe CAVALLARO 
915286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
916286a8372SGiuseppe CAVALLARO {
917286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
918286a8372SGiuseppe CAVALLARO 
919286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
920286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
921286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
922286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
923d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
924286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
925286a8372SGiuseppe CAVALLARO 	else
926d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
927286a8372SGiuseppe CAVALLARO 
928286a8372SGiuseppe CAVALLARO 	return ret;
929286a8372SGiuseppe CAVALLARO }
930286a8372SGiuseppe CAVALLARO 
93132ceabcaSGiuseppe CAVALLARO /**
932732fdf0eSGiuseppe CAVALLARO  * stmmac_clear_descriptors - clear descriptors
93332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
93432ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
93532ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
93632ceabcaSGiuseppe CAVALLARO  */
937c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
938c24602efSGiuseppe CAVALLARO {
939c24602efSGiuseppe CAVALLARO 	int i;
940c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
941c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
942c24602efSGiuseppe CAVALLARO 
943c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
944c24602efSGiuseppe CAVALLARO 	for (i = 0; i < rxsize; i++)
945c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
946c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
947c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
948c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
949c24602efSGiuseppe CAVALLARO 		else
950c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
951c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
952c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
953c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
954c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
955c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
956c24602efSGiuseppe CAVALLARO 						     priv->mode,
957c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
958c24602efSGiuseppe CAVALLARO 		else
959c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
960c24602efSGiuseppe CAVALLARO 						     priv->mode,
961c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
962c24602efSGiuseppe CAVALLARO }
963c24602efSGiuseppe CAVALLARO 
964732fdf0eSGiuseppe CAVALLARO /**
965732fdf0eSGiuseppe CAVALLARO  * stmmac_init_rx_buffers - init the RX descriptor buffer.
966732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
967732fdf0eSGiuseppe CAVALLARO  * @p: descriptor pointer
968732fdf0eSGiuseppe CAVALLARO  * @i: descriptor index
969732fdf0eSGiuseppe CAVALLARO  * @flags: gfp flag.
970732fdf0eSGiuseppe CAVALLARO  * Description: this function is called to allocate a receive buffer, perform
971732fdf0eSGiuseppe CAVALLARO  * the DMA mapping and init the descriptor.
972732fdf0eSGiuseppe CAVALLARO  */
973c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
974777da230SGiuseppe CAVALLARO 				  int i, gfp_t flags)
975c24602efSGiuseppe CAVALLARO {
976c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
977c24602efSGiuseppe CAVALLARO 
978c24602efSGiuseppe CAVALLARO 	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
979777da230SGiuseppe CAVALLARO 				 flags);
98056329137SBartlomiej Zolnierkiewicz 	if (!skb) {
981c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
98256329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
983c24602efSGiuseppe CAVALLARO 	}
984c24602efSGiuseppe CAVALLARO 	skb_reserve(skb, NET_IP_ALIGN);
985c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
986c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
987c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
988c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
98956329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
99056329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
99156329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
99256329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
99356329137SBartlomiej Zolnierkiewicz 	}
994c24602efSGiuseppe CAVALLARO 
995c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
996c24602efSGiuseppe CAVALLARO 
99729896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
998c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
99929896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
1000c24602efSGiuseppe CAVALLARO 
1001c24602efSGiuseppe CAVALLARO 	return 0;
1002c24602efSGiuseppe CAVALLARO }
1003c24602efSGiuseppe CAVALLARO 
100456329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
100556329137SBartlomiej Zolnierkiewicz {
100656329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
100756329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
100856329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
100956329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
101056329137SBartlomiej Zolnierkiewicz 	}
101156329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
101256329137SBartlomiej Zolnierkiewicz }
101356329137SBartlomiej Zolnierkiewicz 
10147ac6653aSJeff Kirsher /**
10157ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
10167ac6653aSJeff Kirsher  * @dev: net device structure
1017732fdf0eSGiuseppe CAVALLARO  * @flags: gfp flag.
10187ac6653aSJeff Kirsher  * Description: this function initializes the DMA RX/TX descriptors
1019286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
1020286a8372SGiuseppe CAVALLARO  * modes.
10217ac6653aSJeff Kirsher  */
1022777da230SGiuseppe CAVALLARO static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
10237ac6653aSJeff Kirsher {
10247ac6653aSJeff Kirsher 	int i;
10257ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
10267ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
10277ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
10284a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
102956329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
10307ac6653aSJeff Kirsher 
103129896a67SGiuseppe CAVALLARO 	if (priv->hw->mode->set_16kib_bfsize)
103229896a67SGiuseppe CAVALLARO 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
1033286a8372SGiuseppe CAVALLARO 
10344a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
1035286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10367ac6653aSJeff Kirsher 
10372618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
10382618abb7SVince Bridgers 
103983d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv))
104083d7af64SGiuseppe CAVALLARO 		pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
10417ac6653aSJeff Kirsher 			 txsize, rxsize, bfsize);
10427ac6653aSJeff Kirsher 
104383d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1044c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1045c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10467ac6653aSJeff Kirsher 
10477ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
104883d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
104983d7af64SGiuseppe CAVALLARO 	}
10507ac6653aSJeff Kirsher 	for (i = 0; i < rxsize; i++) {
1051c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1052c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1053c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1054c24602efSGiuseppe CAVALLARO 		else
1055c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10567ac6653aSJeff Kirsher 
1057777da230SGiuseppe CAVALLARO 		ret = stmmac_init_rx_buffers(priv, p, i, flags);
105856329137SBartlomiej Zolnierkiewicz 		if (ret)
105956329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1060286a8372SGiuseppe CAVALLARO 
106183d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
106283d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
106383d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
106483d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10657ac6653aSJeff Kirsher 	}
10667ac6653aSJeff Kirsher 	priv->cur_rx = 0;
10677ac6653aSJeff Kirsher 	priv->dirty_rx = (unsigned int)(i - rxsize);
10687ac6653aSJeff Kirsher 	buf_sz = bfsize;
10697ac6653aSJeff Kirsher 
1070c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1071c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1072c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
107329896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
1074c24602efSGiuseppe CAVALLARO 					     rxsize, 1);
107529896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1076c24602efSGiuseppe CAVALLARO 					     txsize, 1);
1077c24602efSGiuseppe CAVALLARO 		} else {
107829896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
1079c24602efSGiuseppe CAVALLARO 					     rxsize, 0);
108029896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1081c24602efSGiuseppe CAVALLARO 					     txsize, 0);
1082c24602efSGiuseppe CAVALLARO 		}
10837ac6653aSJeff Kirsher 	}
1084286a8372SGiuseppe CAVALLARO 
1085c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1086c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++) {
1087c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1088c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1089c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1090c24602efSGiuseppe CAVALLARO 		else
1091c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1092c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1093362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].buf = 0;
1094362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].map_as_page = false;
1095c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
10964a7d666aSGiuseppe CAVALLARO 	}
1097c24602efSGiuseppe CAVALLARO 
10987ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
10997ac6653aSJeff Kirsher 	priv->cur_tx = 0;
110038979574SBeniamino Galvani 	netdev_reset_queue(priv->dev);
11017ac6653aSJeff Kirsher 
1102c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
11037ac6653aSJeff Kirsher 
1104c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1105c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
110656329137SBartlomiej Zolnierkiewicz 
110756329137SBartlomiej Zolnierkiewicz 	return 0;
110856329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
110956329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
111056329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
111156329137SBartlomiej Zolnierkiewicz 	return ret;
11127ac6653aSJeff Kirsher }
11137ac6653aSJeff Kirsher 
11147ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
11157ac6653aSJeff Kirsher {
11167ac6653aSJeff Kirsher 	int i;
11177ac6653aSJeff Kirsher 
111856329137SBartlomiej Zolnierkiewicz 	for (i = 0; i < priv->dma_rx_size; i++)
111956329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
11207ac6653aSJeff Kirsher }
11217ac6653aSJeff Kirsher 
11227ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11237ac6653aSJeff Kirsher {
11247ac6653aSJeff Kirsher 	int i;
11257ac6653aSJeff Kirsher 
11267ac6653aSJeff Kirsher 	for (i = 0; i < priv->dma_tx_size; i++) {
1127c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
112875e4364fSdamuzi000 
1129c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1130c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1131c24602efSGiuseppe CAVALLARO 		else
1132c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1133c24602efSGiuseppe CAVALLARO 
1134362b37beSGiuseppe CAVALLARO 		if (priv->tx_skbuff_dma[i].buf) {
1135362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[i].map_as_page)
1136362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1137362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[i].buf,
11387ac6653aSJeff Kirsher 					       priv->hw->desc->get_tx_len(p),
11397ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1140362b37beSGiuseppe CAVALLARO 			else
1141362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1142362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[i].buf,
1143362b37beSGiuseppe CAVALLARO 						 priv->hw->desc->get_tx_len(p),
1144362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
114575e4364fSdamuzi000 		}
114675e4364fSdamuzi000 
114775e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11487ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11497ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
1150362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].buf = 0;
1151362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].map_as_page = false;
11527ac6653aSJeff Kirsher 		}
11537ac6653aSJeff Kirsher 	}
11547ac6653aSJeff Kirsher }
11557ac6653aSJeff Kirsher 
1156732fdf0eSGiuseppe CAVALLARO /**
1157732fdf0eSGiuseppe CAVALLARO  * alloc_dma_desc_resources - alloc TX/RX resources.
1158732fdf0eSGiuseppe CAVALLARO  * @priv: private structure
1159732fdf0eSGiuseppe CAVALLARO  * Description: according to which descriptor can be used (extend or basic)
1160732fdf0eSGiuseppe CAVALLARO  * this function allocates the resources for TX and RX paths. In case of
1161732fdf0eSGiuseppe CAVALLARO  * reception, for example, it pre-allocated the RX socket buffer in order to
1162732fdf0eSGiuseppe CAVALLARO  * allow zero-copy mechanism.
1163732fdf0eSGiuseppe CAVALLARO  */
116409f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
116509f8d696SSrinivas Kandagatla {
116609f8d696SSrinivas Kandagatla 	unsigned int txsize = priv->dma_tx_size;
116709f8d696SSrinivas Kandagatla 	unsigned int rxsize = priv->dma_rx_size;
116809f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
116909f8d696SSrinivas Kandagatla 
117009f8d696SSrinivas Kandagatla 	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
117109f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
117209f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
117309f8d696SSrinivas Kandagatla 		return -ENOMEM;
117409f8d696SSrinivas Kandagatla 
117509f8d696SSrinivas Kandagatla 	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
117609f8d696SSrinivas Kandagatla 					GFP_KERNEL);
117709f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
117809f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
117909f8d696SSrinivas Kandagatla 
1180362b37beSGiuseppe CAVALLARO 	priv->tx_skbuff_dma = kmalloc_array(txsize,
1181362b37beSGiuseppe CAVALLARO 					    sizeof(*priv->tx_skbuff_dma),
118209f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
118309f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
118409f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
118509f8d696SSrinivas Kandagatla 
118609f8d696SSrinivas Kandagatla 	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
118709f8d696SSrinivas Kandagatla 					GFP_KERNEL);
118809f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
118909f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
119009f8d696SSrinivas Kandagatla 
119109f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
119209f8d696SSrinivas Kandagatla 		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
119309f8d696SSrinivas Kandagatla 						   sizeof(struct
119409f8d696SSrinivas Kandagatla 							  dma_extended_desc),
119509f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
119609f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
119709f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
119809f8d696SSrinivas Kandagatla 			goto err_dma;
119909f8d696SSrinivas Kandagatla 
120009f8d696SSrinivas Kandagatla 		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
120109f8d696SSrinivas Kandagatla 						   sizeof(struct
120209f8d696SSrinivas Kandagatla 							  dma_extended_desc),
120309f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
120409f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
120509f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
120609f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
120709f8d696SSrinivas Kandagatla 					sizeof(struct dma_extended_desc),
120809f8d696SSrinivas Kandagatla 					priv->dma_erx, priv->dma_rx_phy);
120909f8d696SSrinivas Kandagatla 			goto err_dma;
121009f8d696SSrinivas Kandagatla 		}
121109f8d696SSrinivas Kandagatla 	} else {
121209f8d696SSrinivas Kandagatla 		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
121309f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
121409f8d696SSrinivas Kandagatla 						  &priv->dma_rx_phy,
121509f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
121609f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
121709f8d696SSrinivas Kandagatla 			goto err_dma;
121809f8d696SSrinivas Kandagatla 
121909f8d696SSrinivas Kandagatla 		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
122009f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
122109f8d696SSrinivas Kandagatla 						  &priv->dma_tx_phy,
122209f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
122309f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
122409f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
122509f8d696SSrinivas Kandagatla 					sizeof(struct dma_desc),
122609f8d696SSrinivas Kandagatla 					priv->dma_rx, priv->dma_rx_phy);
122709f8d696SSrinivas Kandagatla 			goto err_dma;
122809f8d696SSrinivas Kandagatla 		}
122909f8d696SSrinivas Kandagatla 	}
123009f8d696SSrinivas Kandagatla 
123109f8d696SSrinivas Kandagatla 	return 0;
123209f8d696SSrinivas Kandagatla 
123309f8d696SSrinivas Kandagatla err_dma:
123409f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
123509f8d696SSrinivas Kandagatla err_tx_skbuff:
123609f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
123709f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
123809f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
123909f8d696SSrinivas Kandagatla err_rx_skbuff:
124009f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
124109f8d696SSrinivas Kandagatla 	return ret;
124209f8d696SSrinivas Kandagatla }
124309f8d696SSrinivas Kandagatla 
12447ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
12457ac6653aSJeff Kirsher {
12467ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
12477ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
12487ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
12497ac6653aSJeff Kirsher 
1250ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1251c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
12527ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12537ac6653aSJeff Kirsher 				  priv->dma_tx_size * sizeof(struct dma_desc),
12547ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
12557ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12567ac6653aSJeff Kirsher 				  priv->dma_rx_size * sizeof(struct dma_desc),
12577ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1258c24602efSGiuseppe CAVALLARO 	} else {
1259c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_tx_size *
1260c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1261c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1262c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_rx_size *
1263c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1264c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1265c24602efSGiuseppe CAVALLARO 	}
12667ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12677ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1268cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12697ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12707ac6653aSJeff Kirsher }
12717ac6653aSJeff Kirsher 
12727ac6653aSJeff Kirsher /**
12737ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
127432ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
1275732fdf0eSGiuseppe CAVALLARO  *  Description: it is used for configuring the DMA operation mode register in
1276732fdf0eSGiuseppe CAVALLARO  *  order to program the tx/rx DMA thresholds or Store-And-Forward mode.
12777ac6653aSJeff Kirsher  */
12787ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12797ac6653aSJeff Kirsher {
1280e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1281e2a240c7SSonic Zhang 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1282e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12837ac6653aSJeff Kirsher 		/*
12847ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12857ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12867ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12877ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12887ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12897ac6653aSJeff Kirsher 		 */
1290ceb69499SGiuseppe CAVALLARO 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
12917ac6653aSJeff Kirsher 		tc = SF_DMA_MODE;
12927ac6653aSJeff Kirsher 	} else
12937ac6653aSJeff Kirsher 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
12947ac6653aSJeff Kirsher }
12957ac6653aSJeff Kirsher 
12967ac6653aSJeff Kirsher /**
1297732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_clean - to manage the transmission completion
129832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
1299732fdf0eSGiuseppe CAVALLARO  * Description: it reclaims the transmit resources after transmission completes.
13007ac6653aSJeff Kirsher  */
13019125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
13027ac6653aSJeff Kirsher {
13037ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
130438979574SBeniamino Galvani 	unsigned int bytes_compl = 0, pkts_compl = 0;
13057ac6653aSJeff Kirsher 
1306a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1307a9097a96SGiuseppe CAVALLARO 
13089125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
13099125cdd1SGiuseppe CAVALLARO 
13107ac6653aSJeff Kirsher 	while (priv->dirty_tx != priv->cur_tx) {
13117ac6653aSJeff Kirsher 		int last;
13127ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_tx % txsize;
13137ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1314c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1315c24602efSGiuseppe CAVALLARO 
1316c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1317c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1318c24602efSGiuseppe CAVALLARO 		else
1319c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
13207ac6653aSJeff Kirsher 
13217ac6653aSJeff Kirsher 		/* Check if the descriptor is owned by the DMA. */
13227ac6653aSJeff Kirsher 		if (priv->hw->desc->get_tx_owner(p))
13237ac6653aSJeff Kirsher 			break;
13247ac6653aSJeff Kirsher 
1325c24602efSGiuseppe CAVALLARO 		/* Verify tx error by looking at the last segment. */
13267ac6653aSJeff Kirsher 		last = priv->hw->desc->get_tx_ls(p);
13277ac6653aSJeff Kirsher 		if (likely(last)) {
13287ac6653aSJeff Kirsher 			int tx_error =
13297ac6653aSJeff Kirsher 			    priv->hw->desc->tx_status(&priv->dev->stats,
13307ac6653aSJeff Kirsher 						      &priv->xstats, p,
13317ac6653aSJeff Kirsher 						      priv->ioaddr);
13327ac6653aSJeff Kirsher 			if (likely(tx_error == 0)) {
13337ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
13347ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
13357ac6653aSJeff Kirsher 			} else
13367ac6653aSJeff Kirsher 				priv->dev->stats.tx_errors++;
1337891434b1SRayagond Kokatanur 
1338891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
13397ac6653aSJeff Kirsher 		}
134083d7af64SGiuseppe CAVALLARO 		if (netif_msg_tx_done(priv))
134183d7af64SGiuseppe CAVALLARO 			pr_debug("%s: curr %d, dirty %d\n", __func__,
13427ac6653aSJeff Kirsher 				 priv->cur_tx, priv->dirty_tx);
13437ac6653aSJeff Kirsher 
1344362b37beSGiuseppe CAVALLARO 		if (likely(priv->tx_skbuff_dma[entry].buf)) {
1345362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[entry].map_as_page)
1346362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1347362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[entry].buf,
13487ac6653aSJeff Kirsher 					       priv->hw->desc->get_tx_len(p),
13497ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1350362b37beSGiuseppe CAVALLARO 			else
1351362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1352362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[entry].buf,
1353362b37beSGiuseppe CAVALLARO 						 priv->hw->desc->get_tx_len(p),
1354362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
1355362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].buf = 0;
1356362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].map_as_page = false;
1357cf32deecSRayagond Kokatanur 		}
135829896a67SGiuseppe CAVALLARO 		priv->hw->mode->clean_desc3(priv, p);
13597ac6653aSJeff Kirsher 
13607ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
136138979574SBeniamino Galvani 			pkts_compl++;
136238979574SBeniamino Galvani 			bytes_compl += skb->len;
13637c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
13647ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
13657ac6653aSJeff Kirsher 		}
13667ac6653aSJeff Kirsher 
13674a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
13687ac6653aSJeff Kirsher 
136913497f58SGiuseppe CAVALLARO 		priv->dirty_tx++;
13707ac6653aSJeff Kirsher 	}
137138979574SBeniamino Galvani 
137238979574SBeniamino Galvani 	netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
137338979574SBeniamino Galvani 
13747ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
13757ac6653aSJeff Kirsher 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
13767ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13777ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
13787ac6653aSJeff Kirsher 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
137983d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
138083d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13817ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13827ac6653aSJeff Kirsher 		}
13837ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13847ac6653aSJeff Kirsher 	}
1385d765955dSGiuseppe CAVALLARO 
1386d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1387d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1388f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1389d765955dSGiuseppe CAVALLARO 	}
1390a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13917ac6653aSJeff Kirsher }
13927ac6653aSJeff Kirsher 
13939125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13947ac6653aSJeff Kirsher {
13957ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
13967ac6653aSJeff Kirsher }
13977ac6653aSJeff Kirsher 
13989125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
13997ac6653aSJeff Kirsher {
14007ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
14017ac6653aSJeff Kirsher }
14027ac6653aSJeff Kirsher 
14037ac6653aSJeff Kirsher /**
1404732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_err - to manage the tx error
140532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
14067ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
1407732fdf0eSGiuseppe CAVALLARO  * in case of transmission errors.
14087ac6653aSJeff Kirsher  */
14097ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
14107ac6653aSJeff Kirsher {
1411c24602efSGiuseppe CAVALLARO 	int i;
1412c24602efSGiuseppe CAVALLARO 	int txsize = priv->dma_tx_size;
14137ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
14147ac6653aSJeff Kirsher 
14157ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
14167ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1417c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
1418c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1419c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1420c24602efSGiuseppe CAVALLARO 						     priv->mode,
1421c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
1422c24602efSGiuseppe CAVALLARO 		else
1423c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1424c24602efSGiuseppe CAVALLARO 						     priv->mode,
1425c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
14267ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
14277ac6653aSJeff Kirsher 	priv->cur_tx = 0;
142838979574SBeniamino Galvani 	netdev_reset_queue(priv->dev);
14297ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
14307ac6653aSJeff Kirsher 
14317ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
14327ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
14337ac6653aSJeff Kirsher }
14347ac6653aSJeff Kirsher 
143532ceabcaSGiuseppe CAVALLARO /**
1436732fdf0eSGiuseppe CAVALLARO  * stmmac_dma_interrupt - DMA ISR
143732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
143832ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
1439732fdf0eSGiuseppe CAVALLARO  * It calls the dwmac dma routine and schedule poll method in case of some
1440732fdf0eSGiuseppe CAVALLARO  * work can be done.
144132ceabcaSGiuseppe CAVALLARO  */
14427ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
14437ac6653aSJeff Kirsher {
14447ac6653aSJeff Kirsher 	int status;
14457ac6653aSJeff Kirsher 
14467ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
14479125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
14489125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
14499125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
14509125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
14519125cdd1SGiuseppe CAVALLARO 		}
14529125cdd1SGiuseppe CAVALLARO 	}
14539125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
14547ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
14557ac6653aSJeff Kirsher 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
14567ac6653aSJeff Kirsher 			tc += 64;
1457c405abe2SSonic Zhang 			if (priv->plat->force_thresh_dma_mode)
1458c405abe2SSonic Zhang 				priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1459c405abe2SSonic Zhang 			else
1460c405abe2SSonic Zhang 				priv->hw->dma->dma_mode(priv->ioaddr, tc,
1461c405abe2SSonic Zhang 					SF_DMA_MODE);
14627ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
14637ac6653aSJeff Kirsher 		}
14647ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
14657ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
14667ac6653aSJeff Kirsher }
14677ac6653aSJeff Kirsher 
146832ceabcaSGiuseppe CAVALLARO /**
146932ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
147032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
147132ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
147232ceabcaSGiuseppe CAVALLARO  */
14731c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
14741c901a46SGiuseppe CAVALLARO {
14751c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14761c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14771c901a46SGiuseppe CAVALLARO 
14781c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14794f795b25SGiuseppe CAVALLARO 
14804f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14811c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14821c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14834f795b25SGiuseppe CAVALLARO 	} else
1484aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14851c901a46SGiuseppe CAVALLARO }
14861c901a46SGiuseppe CAVALLARO 
1487732fdf0eSGiuseppe CAVALLARO /**
1488732fdf0eSGiuseppe CAVALLARO  * stmmac_get_synopsys_id - return the SYINID.
1489732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
1490732fdf0eSGiuseppe CAVALLARO  * Description: this simple function is to decode and return the SYINID
1491732fdf0eSGiuseppe CAVALLARO  * starting from the HW core register.
1492732fdf0eSGiuseppe CAVALLARO  */
1493f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1494f0b9d786SGiuseppe CAVALLARO {
1495f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1496f0b9d786SGiuseppe CAVALLARO 
1497ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1498f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1499f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1500f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1501f0b9d786SGiuseppe CAVALLARO 
1502cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1503f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1504f0b9d786SGiuseppe CAVALLARO 
1505f0b9d786SGiuseppe CAVALLARO 		return synid;
1506f0b9d786SGiuseppe CAVALLARO 	}
1507f0b9d786SGiuseppe CAVALLARO 	return 0;
1508f0b9d786SGiuseppe CAVALLARO }
1509e7434821SGiuseppe CAVALLARO 
151019e30c14SGiuseppe CAVALLARO /**
1511732fdf0eSGiuseppe CAVALLARO  * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
151232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
151332ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
1514732fdf0eSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it checks if the extended descriptors are
1515732fdf0eSGiuseppe CAVALLARO  * supported by the HW capability register.
1516ff3dd78cSGiuseppe CAVALLARO  */
151719e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
151819e30c14SGiuseppe CAVALLARO {
151919e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
152019e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1521c24602efSGiuseppe CAVALLARO 
1522c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1523c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1524c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1525c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1526c24602efSGiuseppe CAVALLARO 		} else
1527c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1528c24602efSGiuseppe CAVALLARO 
152919e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
153019e30c14SGiuseppe CAVALLARO 	} else {
153119e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
153219e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
153319e30c14SGiuseppe CAVALLARO 	}
153419e30c14SGiuseppe CAVALLARO }
153519e30c14SGiuseppe CAVALLARO 
153619e30c14SGiuseppe CAVALLARO /**
1537732fdf0eSGiuseppe CAVALLARO  * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
153832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
153919e30c14SGiuseppe CAVALLARO  * Description:
154019e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1541e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
154219e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
154319e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1544e7434821SGiuseppe CAVALLARO  */
1545e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1546e7434821SGiuseppe CAVALLARO {
15475e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
15483c20f72fSGiuseppe CAVALLARO 
15495e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
15505e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1551e7434821SGiuseppe CAVALLARO 
15521db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
15531db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
15541db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
15551db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1556ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
15571db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
15581db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
15591db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
15601db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
15611db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
15621db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
15631db123fbSRayagond Kokatanur 		/* MMC */
15641db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1565e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
15661db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
15671db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1568e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
15691db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
15701db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1571e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
15721db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
15731db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1574e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
15751db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
15761db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
15771db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
15781db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
15791db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
15801db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
15811db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1582e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15831db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15841db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15851db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15861db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1587e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1588ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
158919e30c14SGiuseppe CAVALLARO 	}
1590e7434821SGiuseppe CAVALLARO 
1591e7434821SGiuseppe CAVALLARO 	return hw_cap;
1592e7434821SGiuseppe CAVALLARO }
1593e7434821SGiuseppe CAVALLARO 
159432ceabcaSGiuseppe CAVALLARO /**
1595732fdf0eSGiuseppe CAVALLARO  * stmmac_check_ether_addr - check if the MAC addr is valid
159632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
159732ceabcaSGiuseppe CAVALLARO  * Description:
159832ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
159932ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
160032ceabcaSGiuseppe CAVALLARO  */
1601bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1602bfab27a1SGiuseppe CAVALLARO {
1603bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
16047ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
1605bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1606bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1607f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1608c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1609bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1610bfab27a1SGiuseppe CAVALLARO 	}
1611c88460b7SHans de Goede }
1612bfab27a1SGiuseppe CAVALLARO 
161332ceabcaSGiuseppe CAVALLARO /**
1614732fdf0eSGiuseppe CAVALLARO  * stmmac_init_dma_engine - DMA init.
161532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
161632ceabcaSGiuseppe CAVALLARO  * Description:
161732ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
161832ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
161932ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
162032ceabcaSGiuseppe CAVALLARO  */
16210f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
16220f1f88a8SGiuseppe CAVALLARO {
16230f1f88a8SGiuseppe CAVALLARO 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
1624b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1625c24602efSGiuseppe CAVALLARO 	int atds = 0;
16260f1f88a8SGiuseppe CAVALLARO 
16270f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
16280f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
16290f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1630b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
16310f1f88a8SGiuseppe CAVALLARO 		burst_len = priv->plat->dma_cfg->burst_len;
16320f1f88a8SGiuseppe CAVALLARO 	}
16330f1f88a8SGiuseppe CAVALLARO 
1634c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1635c24602efSGiuseppe CAVALLARO 		atds = 1;
1636c24602efSGiuseppe CAVALLARO 
1637b9cde0a8SGiuseppe CAVALLARO 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
16380f1f88a8SGiuseppe CAVALLARO 				   burst_len, priv->dma_tx_phy,
1639c24602efSGiuseppe CAVALLARO 				   priv->dma_rx_phy, atds);
16400f1f88a8SGiuseppe CAVALLARO }
16410f1f88a8SGiuseppe CAVALLARO 
1642bfab27a1SGiuseppe CAVALLARO /**
1643732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_timer - mitigation sw timer for tx.
16449125cdd1SGiuseppe CAVALLARO  * @data: data pointer
16459125cdd1SGiuseppe CAVALLARO  * Description:
16469125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
16479125cdd1SGiuseppe CAVALLARO  */
16489125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
16499125cdd1SGiuseppe CAVALLARO {
16509125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
16519125cdd1SGiuseppe CAVALLARO 
16529125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
16539125cdd1SGiuseppe CAVALLARO }
16549125cdd1SGiuseppe CAVALLARO 
16559125cdd1SGiuseppe CAVALLARO /**
1656732fdf0eSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce - init tx mitigation options.
165732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
16589125cdd1SGiuseppe CAVALLARO  * Description:
16599125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
16609125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
16619125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
16629125cdd1SGiuseppe CAVALLARO  */
16639125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
16649125cdd1SGiuseppe CAVALLARO {
16659125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
16669125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
16679125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
16689125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
16699125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
16709125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
16719125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
16729125cdd1SGiuseppe CAVALLARO }
16739125cdd1SGiuseppe CAVALLARO 
16749125cdd1SGiuseppe CAVALLARO /**
1675732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_setup - setup mac in a usable state.
1676523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1677523f11b5SSrinivas Kandagatla  *  Description:
1678732fdf0eSGiuseppe CAVALLARO  *  this is the main function to setup the HW in a usable state because the
1679732fdf0eSGiuseppe CAVALLARO  *  dma engine is reset, the core registers are configured (e.g. AXI,
1680732fdf0eSGiuseppe CAVALLARO  *  Checksum features, timers). The DMA is ready to start receiving and
1681732fdf0eSGiuseppe CAVALLARO  *  transmitting.
1682523f11b5SSrinivas Kandagatla  *  Return value:
1683523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1684523f11b5SSrinivas Kandagatla  *  file on failure.
1685523f11b5SSrinivas Kandagatla  */
1686fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
1687523f11b5SSrinivas Kandagatla {
1688523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1689523f11b5SSrinivas Kandagatla 	int ret;
1690523f11b5SSrinivas Kandagatla 
1691523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1692523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1693523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1694523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1695523f11b5SSrinivas Kandagatla 		return ret;
1696523f11b5SSrinivas Kandagatla 	}
1697523f11b5SSrinivas Kandagatla 
1698523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
16997ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
1700523f11b5SSrinivas Kandagatla 
1701523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1702523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1703523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1704523f11b5SSrinivas Kandagatla 
1705523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
17067ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
1707523f11b5SSrinivas Kandagatla 
1708978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
1709978aded4SGiuseppe CAVALLARO 	if (!ret) {
1710978aded4SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload disabled\n");
1711978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
1712d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
1713978aded4SGiuseppe CAVALLARO 	}
1714978aded4SGiuseppe CAVALLARO 
1715523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1716523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1717523f11b5SSrinivas Kandagatla 
1718523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1719523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1720523f11b5SSrinivas Kandagatla 
1721523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1722523f11b5SSrinivas Kandagatla 
1723fe131929SHuacai Chen 	if (init_ptp) {
1724523f11b5SSrinivas Kandagatla 		ret = stmmac_init_ptp(priv);
17257509edd6SHans de Goede 		if (ret && ret != -EOPNOTSUPP)
1726523f11b5SSrinivas Kandagatla 			pr_warn("%s: failed PTP initialisation\n", __func__);
1727fe131929SHuacai Chen 	}
1728523f11b5SSrinivas Kandagatla 
172950fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
1730523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1731523f11b5SSrinivas Kandagatla 	if (ret < 0)
1732523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1733523f11b5SSrinivas Kandagatla #endif
1734523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1735523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1736523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1737523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1738523f11b5SSrinivas Kandagatla 
1739523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1740523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
17417ed24bbeSVince Bridgers 		priv->hw->mac->dump_regs(priv->hw);
1742523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1743523f11b5SSrinivas Kandagatla 	}
1744523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1745523f11b5SSrinivas Kandagatla 
1746523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1747523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1748523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1749523f11b5SSrinivas Kandagatla 	}
1750523f11b5SSrinivas Kandagatla 
1751523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
17527ed24bbeSVince Bridgers 		priv->hw->mac->ctrl_ane(priv->hw, 0);
1753523f11b5SSrinivas Kandagatla 
1754523f11b5SSrinivas Kandagatla 	return 0;
1755523f11b5SSrinivas Kandagatla }
1756523f11b5SSrinivas Kandagatla 
1757523f11b5SSrinivas Kandagatla /**
17587ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
17597ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
17607ac6653aSJeff Kirsher  *  Description:
17617ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
17627ac6653aSJeff Kirsher  *  Return value:
17637ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
17647ac6653aSJeff Kirsher  *  file on failure.
17657ac6653aSJeff Kirsher  */
17667ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
17677ac6653aSJeff Kirsher {
17687ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17697ac6653aSJeff Kirsher 	int ret;
17707ac6653aSJeff Kirsher 
17714bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
17724bfcbd7aSFrancesco Virlinzi 
17734d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
17744d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
17757ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1776e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1777e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1778e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
177989df20d9SHans de Goede 			return ret;
17807ac6653aSJeff Kirsher 		}
1781e58bb43fSGiuseppe CAVALLARO 	}
17827ac6653aSJeff Kirsher 
1783523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1784523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1785523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1786523f11b5SSrinivas Kandagatla 
17877ac6653aSJeff Kirsher 	/* Create and initialize the TX/RX descriptors chains. */
17887ac6653aSJeff Kirsher 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
17897ac6653aSJeff Kirsher 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
17907ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
179156329137SBartlomiej Zolnierkiewicz 
17927262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
179309f8d696SSrinivas Kandagatla 	if (ret < 0) {
179409f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
179509f8d696SSrinivas Kandagatla 		goto dma_desc_error;
179609f8d696SSrinivas Kandagatla 	}
179709f8d696SSrinivas Kandagatla 
1798777da230SGiuseppe CAVALLARO 	ret = init_dma_desc_rings(dev, GFP_KERNEL);
1799777da230SGiuseppe CAVALLARO 	if (ret < 0) {
1800777da230SGiuseppe CAVALLARO 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1801777da230SGiuseppe CAVALLARO 		goto init_error;
1802777da230SGiuseppe CAVALLARO 	}
1803777da230SGiuseppe CAVALLARO 
1804fe131929SHuacai Chen 	ret = stmmac_hw_setup(dev, true);
180556329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1806523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1807c9324d18SGiuseppe CAVALLARO 		goto init_error;
18087ac6653aSJeff Kirsher 	}
18097ac6653aSJeff Kirsher 
1810777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
1811777da230SGiuseppe CAVALLARO 
1812523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1813523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
18147ac6653aSJeff Kirsher 
18157ac6653aSJeff Kirsher 	/* Request the IRQ lines */
18167ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
18177ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
18187ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
18197ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
18207ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1821c9324d18SGiuseppe CAVALLARO 		goto init_error;
18227ac6653aSJeff Kirsher 	}
18237ac6653aSJeff Kirsher 
18247a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
18257a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
18267a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
18277a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
18287a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1829ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1830ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1831c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
18327a13f8f5SFrancesco Virlinzi 		}
18337a13f8f5SFrancesco Virlinzi 	}
18347a13f8f5SFrancesco Virlinzi 
1835d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1836d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
1837d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1838d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1839d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1840d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1841d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1842c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1843d765955dSGiuseppe CAVALLARO 		}
1844d765955dSGiuseppe CAVALLARO 	}
1845d765955dSGiuseppe CAVALLARO 
18467ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
18477ac6653aSJeff Kirsher 	netif_start_queue(dev);
18487ac6653aSJeff Kirsher 
18497ac6653aSJeff Kirsher 	return 0;
18507ac6653aSJeff Kirsher 
1851c9324d18SGiuseppe CAVALLARO lpiirq_error:
1852d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1853d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1854c9324d18SGiuseppe CAVALLARO wolirq_error:
18557a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
18567a13f8f5SFrancesco Virlinzi 
1857c9324d18SGiuseppe CAVALLARO init_error:
1858c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
185956329137SBartlomiej Zolnierkiewicz dma_desc_error:
18607ac6653aSJeff Kirsher 	if (priv->phydev)
18617ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18624bfcbd7aSFrancesco Virlinzi 
18637ac6653aSJeff Kirsher 	return ret;
18647ac6653aSJeff Kirsher }
18657ac6653aSJeff Kirsher 
18667ac6653aSJeff Kirsher /**
18677ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
18687ac6653aSJeff Kirsher  *  @dev : device pointer.
18697ac6653aSJeff Kirsher  *  Description:
18707ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
18717ac6653aSJeff Kirsher  */
18727ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
18737ac6653aSJeff Kirsher {
18747ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18757ac6653aSJeff Kirsher 
1876d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1877d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1878d765955dSGiuseppe CAVALLARO 
18797ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
18807ac6653aSJeff Kirsher 	if (priv->phydev) {
18817ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
18827ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18837ac6653aSJeff Kirsher 		priv->phydev = NULL;
18847ac6653aSJeff Kirsher 	}
18857ac6653aSJeff Kirsher 
18867ac6653aSJeff Kirsher 	netif_stop_queue(dev);
18877ac6653aSJeff Kirsher 
18887ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
18897ac6653aSJeff Kirsher 
18909125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
18919125cdd1SGiuseppe CAVALLARO 
18927ac6653aSJeff Kirsher 	/* Free the IRQ lines */
18937ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
18947a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
18957a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1896d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
1897d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
18987ac6653aSJeff Kirsher 
18997ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
19007ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
19017ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
19027ac6653aSJeff Kirsher 
19037ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
19047ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
19057ac6653aSJeff Kirsher 
19067ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1907bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
19087ac6653aSJeff Kirsher 
19097ac6653aSJeff Kirsher 	netif_carrier_off(dev);
19107ac6653aSJeff Kirsher 
191150fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
1912bfab27a1SGiuseppe CAVALLARO 	stmmac_exit_fs();
1913bfab27a1SGiuseppe CAVALLARO #endif
1914bfab27a1SGiuseppe CAVALLARO 
191592ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
191692ba6888SRayagond Kokatanur 
19177ac6653aSJeff Kirsher 	return 0;
19187ac6653aSJeff Kirsher }
19197ac6653aSJeff Kirsher 
19207ac6653aSJeff Kirsher /**
1921732fdf0eSGiuseppe CAVALLARO  *  stmmac_xmit - Tx entry point of the driver
19227ac6653aSJeff Kirsher  *  @skb : the socket buffer
19237ac6653aSJeff Kirsher  *  @dev : device pointer
192432ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
192532ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
192632ceabcaSGiuseppe CAVALLARO  *  and SG feature.
19277ac6653aSJeff Kirsher  */
19287ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
19297ac6653aSJeff Kirsher {
19307ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
19317ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
19327ac6653aSJeff Kirsher 	unsigned int entry;
19334a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
19347ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
19357ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
1936286a8372SGiuseppe CAVALLARO 	unsigned int nopaged_len = skb_headlen(skb);
193729896a67SGiuseppe CAVALLARO 	unsigned int enh_desc = priv->plat->enh_desc;
19387ac6653aSJeff Kirsher 
193916ee817eSFabrice Gasnier 	spin_lock(&priv->tx_lock);
194016ee817eSFabrice Gasnier 
19417ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
194216ee817eSFabrice Gasnier 		spin_unlock(&priv->tx_lock);
19437ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
19447ac6653aSJeff Kirsher 			netif_stop_queue(dev);
19457ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1946ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
19477ac6653aSJeff Kirsher 		}
19487ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
19497ac6653aSJeff Kirsher 	}
19507ac6653aSJeff Kirsher 
1951d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1952d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1953d765955dSGiuseppe CAVALLARO 
19547ac6653aSJeff Kirsher 	entry = priv->cur_tx % txsize;
19557ac6653aSJeff Kirsher 
19567ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
19577ac6653aSJeff Kirsher 
1958c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc)
1959c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1960c24602efSGiuseppe CAVALLARO 	else
19617ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1962c24602efSGiuseppe CAVALLARO 
19637ac6653aSJeff Kirsher 	first = desc;
19647ac6653aSJeff Kirsher 
19654a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
196629896a67SGiuseppe CAVALLARO 	if (enh_desc)
196729896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
196829896a67SGiuseppe CAVALLARO 
19694a7d666aSGiuseppe CAVALLARO 	if (likely(!is_jumbo)) {
19707ac6653aSJeff Kirsher 		desc->des2 = dma_map_single(priv->device, skb->data,
19717ac6653aSJeff Kirsher 					    nopaged_len, DMA_TO_DEVICE);
1972362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
1973362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
1974362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
19757ac6653aSJeff Kirsher 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
19764a7d666aSGiuseppe CAVALLARO 						csum_insertion, priv->mode);
197729896a67SGiuseppe CAVALLARO 	} else {
1978c24602efSGiuseppe CAVALLARO 		desc = first;
197929896a67SGiuseppe CAVALLARO 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
1980362b37beSGiuseppe CAVALLARO 		if (unlikely(entry < 0))
1981362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
198229896a67SGiuseppe CAVALLARO 	}
19837ac6653aSJeff Kirsher 
19847ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
19859e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
19869e903e08SEric Dumazet 		int len = skb_frag_size(frag);
19877ac6653aSJeff Kirsher 
198875e4364fSdamuzi000 		priv->tx_skbuff[entry] = NULL;
19897ac6653aSJeff Kirsher 		entry = (++priv->cur_tx) % txsize;
1990c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1991c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
1992c24602efSGiuseppe CAVALLARO 		else
19937ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
19947ac6653aSJeff Kirsher 
1995f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1996f722380dSIan Campbell 					      DMA_TO_DEVICE);
1997362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
1998362b37beSGiuseppe CAVALLARO 			goto dma_map_err; /* should reuse desc w/o issues */
1999362b37beSGiuseppe CAVALLARO 
2000362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
2001362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].map_as_page = true;
20024a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
20034a7d666aSGiuseppe CAVALLARO 						priv->mode);
20047ac6653aSJeff Kirsher 		wmb();
20057ac6653aSJeff Kirsher 		priv->hw->desc->set_tx_owner(desc);
20068e839891SDeepak Sikri 		wmb();
20077ac6653aSJeff Kirsher 	}
20087ac6653aSJeff Kirsher 
200975e4364fSdamuzi000 	priv->tx_skbuff[entry] = skb;
201075e4364fSdamuzi000 
20119125cdd1SGiuseppe CAVALLARO 	/* Finalize the latest segment. */
20127ac6653aSJeff Kirsher 	priv->hw->desc->close_tx_desc(desc);
20137ac6653aSJeff Kirsher 
20147ac6653aSJeff Kirsher 	wmb();
20159125cdd1SGiuseppe CAVALLARO 	/* According to the coalesce parameter the IC bit for the latest
20169125cdd1SGiuseppe CAVALLARO 	 * segment could be reset and the timer re-started to invoke the
20179125cdd1SGiuseppe CAVALLARO 	 * stmmac_tx function. This approach takes care about the fragments.
20189125cdd1SGiuseppe CAVALLARO 	 */
20199125cdd1SGiuseppe CAVALLARO 	priv->tx_count_frames += nfrags + 1;
20209125cdd1SGiuseppe CAVALLARO 	if (priv->tx_coal_frames > priv->tx_count_frames) {
20219125cdd1SGiuseppe CAVALLARO 		priv->hw->desc->clear_tx_ic(desc);
20229125cdd1SGiuseppe CAVALLARO 		priv->xstats.tx_reset_ic_bit++;
20239125cdd1SGiuseppe CAVALLARO 		mod_timer(&priv->txtimer,
20249125cdd1SGiuseppe CAVALLARO 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
20259125cdd1SGiuseppe CAVALLARO 	} else
20269125cdd1SGiuseppe CAVALLARO 		priv->tx_count_frames = 0;
20277ac6653aSJeff Kirsher 
20287ac6653aSJeff Kirsher 	/* To avoid raise condition */
20297ac6653aSJeff Kirsher 	priv->hw->desc->set_tx_owner(first);
20308e839891SDeepak Sikri 	wmb();
20317ac6653aSJeff Kirsher 
20327ac6653aSJeff Kirsher 	priv->cur_tx++;
20337ac6653aSJeff Kirsher 
20347ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
203583d7af64SGiuseppe CAVALLARO 		pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d",
2036ceb69499SGiuseppe CAVALLARO 			__func__, (priv->cur_tx % txsize),
2037ceb69499SGiuseppe CAVALLARO 			(priv->dirty_tx % txsize), entry, first, nfrags);
203883d7af64SGiuseppe CAVALLARO 
2039c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2040c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
2041c24602efSGiuseppe CAVALLARO 		else
2042c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
2043c24602efSGiuseppe CAVALLARO 
204483d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
20457ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
20467ac6653aSJeff Kirsher 	}
20477ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
204883d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
204983d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
20507ac6653aSJeff Kirsher 		netif_stop_queue(dev);
20517ac6653aSJeff Kirsher 	}
20527ac6653aSJeff Kirsher 
20537ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
20547ac6653aSJeff Kirsher 
2055891434b1SRayagond Kokatanur 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2056891434b1SRayagond Kokatanur 		     priv->hwts_tx_en)) {
2057891434b1SRayagond Kokatanur 		/* declare that device is doing timestamping */
2058891434b1SRayagond Kokatanur 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2059891434b1SRayagond Kokatanur 		priv->hw->desc->enable_tx_timestamp(first);
2060891434b1SRayagond Kokatanur 	}
2061891434b1SRayagond Kokatanur 
2062891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
20637ac6653aSJeff Kirsher 		skb_tx_timestamp(skb);
20647ac6653aSJeff Kirsher 
206538979574SBeniamino Galvani 	netdev_sent_queue(dev, skb->len);
20667ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
20677ac6653aSJeff Kirsher 
2068a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
2069362b37beSGiuseppe CAVALLARO 	return NETDEV_TX_OK;
2070a9097a96SGiuseppe CAVALLARO 
2071362b37beSGiuseppe CAVALLARO dma_map_err:
2072758a0ab5SFabrice Gasnier 	spin_unlock(&priv->tx_lock);
2073362b37beSGiuseppe CAVALLARO 	dev_err(priv->device, "Tx dma map failed\n");
2074362b37beSGiuseppe CAVALLARO 	dev_kfree_skb(skb);
2075362b37beSGiuseppe CAVALLARO 	priv->dev->stats.tx_dropped++;
20767ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
20777ac6653aSJeff Kirsher }
20787ac6653aSJeff Kirsher 
2079b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
2080b9381985SVince Bridgers {
2081b9381985SVince Bridgers 	struct ethhdr *ehdr;
2082b9381985SVince Bridgers 	u16 vlanid;
2083b9381985SVince Bridgers 
2084b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
2085b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
2086b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
2087b9381985SVince Bridgers 		/* pop the vlan tag */
2088b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
2089b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
2090b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
2091b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
2092b9381985SVince Bridgers 	}
2093b9381985SVince Bridgers }
2094b9381985SVince Bridgers 
2095b9381985SVince Bridgers 
209632ceabcaSGiuseppe CAVALLARO /**
2097732fdf0eSGiuseppe CAVALLARO  * stmmac_rx_refill - refill used skb preallocated buffers
209832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
209932ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
210032ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
210132ceabcaSGiuseppe CAVALLARO  */
21027ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
21037ac6653aSJeff Kirsher {
21047ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
21057ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
21067ac6653aSJeff Kirsher 
21077ac6653aSJeff Kirsher 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
21087ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_rx % rxsize;
2109c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2110c24602efSGiuseppe CAVALLARO 
2111c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2112c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2113c24602efSGiuseppe CAVALLARO 		else
2114c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2115c24602efSGiuseppe CAVALLARO 
21167ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
21177ac6653aSJeff Kirsher 			struct sk_buff *skb;
21187ac6653aSJeff Kirsher 
2119acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
21207ac6653aSJeff Kirsher 
21217ac6653aSJeff Kirsher 			if (unlikely(skb == NULL))
21227ac6653aSJeff Kirsher 				break;
21237ac6653aSJeff Kirsher 
21247ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
21257ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
21267ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
21277ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
2128362b37beSGiuseppe CAVALLARO 			if (dma_mapping_error(priv->device,
2129362b37beSGiuseppe CAVALLARO 					      priv->rx_skbuff_dma[entry])) {
2130362b37beSGiuseppe CAVALLARO 				dev_err(priv->device, "Rx dma map failed\n");
2131362b37beSGiuseppe CAVALLARO 				dev_kfree_skb(skb);
2132362b37beSGiuseppe CAVALLARO 				break;
2133362b37beSGiuseppe CAVALLARO 			}
2134c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2135286a8372SGiuseppe CAVALLARO 
213629896a67SGiuseppe CAVALLARO 			priv->hw->mode->refill_desc3(priv, p);
2137286a8372SGiuseppe CAVALLARO 
213883d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
213983d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
21407ac6653aSJeff Kirsher 		}
21417ac6653aSJeff Kirsher 		wmb();
2142c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
21438e839891SDeepak Sikri 		wmb();
21447ac6653aSJeff Kirsher 	}
21457ac6653aSJeff Kirsher }
21467ac6653aSJeff Kirsher 
214732ceabcaSGiuseppe CAVALLARO /**
2148732fdf0eSGiuseppe CAVALLARO  * stmmac_rx - manage the receive process
214932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
215032ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
215132ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
215232ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
215332ceabcaSGiuseppe CAVALLARO  */
21547ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
21557ac6653aSJeff Kirsher {
21567ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
21577ac6653aSJeff Kirsher 	unsigned int entry = priv->cur_rx % rxsize;
21587ac6653aSJeff Kirsher 	unsigned int next_entry;
21597ac6653aSJeff Kirsher 	unsigned int count = 0;
2160d2afb5bdSGiuseppe CAVALLARO 	int coe = priv->hw->rx_csum;
21617ac6653aSJeff Kirsher 
216283d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
216383d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2164c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2165c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
2166c24602efSGiuseppe CAVALLARO 		else
2167c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
21687ac6653aSJeff Kirsher 	}
2169c24602efSGiuseppe CAVALLARO 	while (count < limit) {
21707ac6653aSJeff Kirsher 		int status;
21719401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
21727ac6653aSJeff Kirsher 
2173c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2174c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2175c24602efSGiuseppe CAVALLARO 		else
2176c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2177c24602efSGiuseppe CAVALLARO 
2178c24602efSGiuseppe CAVALLARO 		if (priv->hw->desc->get_rx_owner(p))
21797ac6653aSJeff Kirsher 			break;
21807ac6653aSJeff Kirsher 
21817ac6653aSJeff Kirsher 		count++;
21827ac6653aSJeff Kirsher 
21837ac6653aSJeff Kirsher 		next_entry = (++priv->cur_rx) % rxsize;
2184c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
21859401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2186c24602efSGiuseppe CAVALLARO 		else
21879401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
21887ac6653aSJeff Kirsher 
21897ac6653aSJeff Kirsher 		/* read the status of the incoming frame */
2190c24602efSGiuseppe CAVALLARO 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2191c24602efSGiuseppe CAVALLARO 						   &priv->xstats, p);
2192c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2193c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2194c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2195c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2196c24602efSGiuseppe CAVALLARO 							   entry);
2197891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
21987ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2199891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2200891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2201891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2202891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2203891434b1SRayagond Kokatanur 				 * device can reuse it.
2204891434b1SRayagond Kokatanur 				 */
2205891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2206891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2207891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2208ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2209ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2210891434b1SRayagond Kokatanur 			}
2211891434b1SRayagond Kokatanur 		} else {
22127ac6653aSJeff Kirsher 			struct sk_buff *skb;
22137ac6653aSJeff Kirsher 			int frame_len;
22147ac6653aSJeff Kirsher 
2215ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2216ceb69499SGiuseppe CAVALLARO 
22177ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2218ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2219ceb69499SGiuseppe CAVALLARO 			 */
22207ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
22217ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
22227ac6653aSJeff Kirsher 
222383d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
22247ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
22257ac6653aSJeff Kirsher 					 p, entry, p->des2);
222683d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
222783d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
222883d7af64SGiuseppe CAVALLARO 						 frame_len, status);
222983d7af64SGiuseppe CAVALLARO 			}
22307ac6653aSJeff Kirsher 			skb = priv->rx_skbuff[entry];
22317ac6653aSJeff Kirsher 			if (unlikely(!skb)) {
22327ac6653aSJeff Kirsher 				pr_err("%s: Inconsistent Rx descriptor chain\n",
22337ac6653aSJeff Kirsher 				       priv->dev->name);
22347ac6653aSJeff Kirsher 				priv->dev->stats.rx_dropped++;
22357ac6653aSJeff Kirsher 				break;
22367ac6653aSJeff Kirsher 			}
22377ac6653aSJeff Kirsher 			prefetch(skb->data - NET_IP_ALIGN);
22387ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = NULL;
22397ac6653aSJeff Kirsher 
2240891434b1SRayagond Kokatanur 			stmmac_get_rx_hwtstamp(priv, entry, skb);
2241891434b1SRayagond Kokatanur 
22427ac6653aSJeff Kirsher 			skb_put(skb, frame_len);
22437ac6653aSJeff Kirsher 			dma_unmap_single(priv->device,
22447ac6653aSJeff Kirsher 					 priv->rx_skbuff_dma[entry],
22457ac6653aSJeff Kirsher 					 priv->dma_buf_sz, DMA_FROM_DEVICE);
224683d7af64SGiuseppe CAVALLARO 
22477ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
224883d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
22497ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
22507ac6653aSJeff Kirsher 			}
225183d7af64SGiuseppe CAVALLARO 
2252b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2253b9381985SVince Bridgers 
22547ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
22557ac6653aSJeff Kirsher 
2256ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
22577ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
225862a2ab93SGiuseppe CAVALLARO 			else
22597ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
226062a2ab93SGiuseppe CAVALLARO 
22617ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
22627ac6653aSJeff Kirsher 
22637ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
22647ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
22657ac6653aSJeff Kirsher 		}
22667ac6653aSJeff Kirsher 		entry = next_entry;
22677ac6653aSJeff Kirsher 	}
22687ac6653aSJeff Kirsher 
22697ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
22707ac6653aSJeff Kirsher 
22717ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
22727ac6653aSJeff Kirsher 
22737ac6653aSJeff Kirsher 	return count;
22747ac6653aSJeff Kirsher }
22757ac6653aSJeff Kirsher 
22767ac6653aSJeff Kirsher /**
22777ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
22787ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
22797ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
22807ac6653aSJeff Kirsher  *	      all interfaces.
22817ac6653aSJeff Kirsher  *  Description :
22829125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
22837ac6653aSJeff Kirsher  */
22847ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
22857ac6653aSJeff Kirsher {
22867ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
22877ac6653aSJeff Kirsher 	int work_done = 0;
22887ac6653aSJeff Kirsher 
22899125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
22909125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
22917ac6653aSJeff Kirsher 
22929125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
22937ac6653aSJeff Kirsher 	if (work_done < budget) {
22947ac6653aSJeff Kirsher 		napi_complete(napi);
22959125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
22967ac6653aSJeff Kirsher 	}
22977ac6653aSJeff Kirsher 	return work_done;
22987ac6653aSJeff Kirsher }
22997ac6653aSJeff Kirsher 
23007ac6653aSJeff Kirsher /**
23017ac6653aSJeff Kirsher  *  stmmac_tx_timeout
23027ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
23037ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
23047284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
23057ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
23067ac6653aSJeff Kirsher  *   in order to transmit a new packet.
23077ac6653aSJeff Kirsher  */
23087ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
23097ac6653aSJeff Kirsher {
23107ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23117ac6653aSJeff Kirsher 
23127ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
23137ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
23147ac6653aSJeff Kirsher }
23157ac6653aSJeff Kirsher 
23167ac6653aSJeff Kirsher /**
231701789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
23187ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
23197ac6653aSJeff Kirsher  *  Description:
23207ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
23217ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
23227ac6653aSJeff Kirsher  *  Return value:
23237ac6653aSJeff Kirsher  *  void.
23247ac6653aSJeff Kirsher  */
232501789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
23267ac6653aSJeff Kirsher {
23277ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23287ac6653aSJeff Kirsher 
23293b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
23307ac6653aSJeff Kirsher }
23317ac6653aSJeff Kirsher 
23327ac6653aSJeff Kirsher /**
23337ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
23347ac6653aSJeff Kirsher  *  @dev : device pointer.
23357ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
23367ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
23377ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
23387ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
23397ac6653aSJeff Kirsher  *  Return value:
23407ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
23417ac6653aSJeff Kirsher  *  file on failure.
23427ac6653aSJeff Kirsher  */
23437ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
23447ac6653aSJeff Kirsher {
23457ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23467ac6653aSJeff Kirsher 	int max_mtu;
23477ac6653aSJeff Kirsher 
23487ac6653aSJeff Kirsher 	if (netif_running(dev)) {
23497ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
23507ac6653aSJeff Kirsher 		return -EBUSY;
23517ac6653aSJeff Kirsher 	}
23527ac6653aSJeff Kirsher 
235348febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
23547ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
23557ac6653aSJeff Kirsher 	else
235645db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
23577ac6653aSJeff Kirsher 
23582618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
23592618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
23602618abb7SVince Bridgers 
23617ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
23627ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
23637ac6653aSJeff Kirsher 		return -EINVAL;
23647ac6653aSJeff Kirsher 	}
23657ac6653aSJeff Kirsher 
23667ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
23677ac6653aSJeff Kirsher 	netdev_update_features(dev);
23687ac6653aSJeff Kirsher 
23697ac6653aSJeff Kirsher 	return 0;
23707ac6653aSJeff Kirsher }
23717ac6653aSJeff Kirsher 
2372c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2373c8f44affSMichał Mirosław 					     netdev_features_t features)
23747ac6653aSJeff Kirsher {
23757ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23767ac6653aSJeff Kirsher 
237738912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
23787ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
2379d2afb5bdSGiuseppe CAVALLARO 
23807ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
23817ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23827ac6653aSJeff Kirsher 
23837ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
23847ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
23857ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2386ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2387ceb69499SGiuseppe CAVALLARO 	 */
23887ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
23897ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23907ac6653aSJeff Kirsher 
23917ac6653aSJeff Kirsher 	return features;
23927ac6653aSJeff Kirsher }
23937ac6653aSJeff Kirsher 
2394d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev,
2395d2afb5bdSGiuseppe CAVALLARO 			       netdev_features_t features)
2396d2afb5bdSGiuseppe CAVALLARO {
2397d2afb5bdSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(netdev);
2398d2afb5bdSGiuseppe CAVALLARO 
2399d2afb5bdSGiuseppe CAVALLARO 	/* Keep the COE Type in case of csum is supporting */
2400d2afb5bdSGiuseppe CAVALLARO 	if (features & NETIF_F_RXCSUM)
2401d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
2402d2afb5bdSGiuseppe CAVALLARO 	else
2403d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
2404d2afb5bdSGiuseppe CAVALLARO 	/* No check needed because rx_coe has been set before and it will be
2405d2afb5bdSGiuseppe CAVALLARO 	 * fixed in case of issue.
2406d2afb5bdSGiuseppe CAVALLARO 	 */
2407d2afb5bdSGiuseppe CAVALLARO 	priv->hw->mac->rx_ipc(priv->hw);
2408d2afb5bdSGiuseppe CAVALLARO 
2409d2afb5bdSGiuseppe CAVALLARO 	return 0;
2410d2afb5bdSGiuseppe CAVALLARO }
2411d2afb5bdSGiuseppe CAVALLARO 
241232ceabcaSGiuseppe CAVALLARO /**
241332ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
241432ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
241532ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
241632ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
2417732fdf0eSGiuseppe CAVALLARO  *  It can call:
2418732fdf0eSGiuseppe CAVALLARO  *  o DMA service routine (to manage incoming frame reception and transmission
2419732fdf0eSGiuseppe CAVALLARO  *    status)
2420732fdf0eSGiuseppe CAVALLARO  *  o Core interrupts to manage: remote wake-up, management counter, LPI
242132ceabcaSGiuseppe CAVALLARO  *    interrupts.
242232ceabcaSGiuseppe CAVALLARO  */
24237ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
24247ac6653aSJeff Kirsher {
24257ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
24267ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24277ac6653aSJeff Kirsher 
242889f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
242989f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
243089f7f2cfSSrinivas Kandagatla 
24317ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
24327ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
24337ac6653aSJeff Kirsher 		return IRQ_NONE;
24347ac6653aSJeff Kirsher 	}
24357ac6653aSJeff Kirsher 
24367ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2437d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
24387ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
24390982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2440d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2441d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
24420982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2443d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
24440982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2445d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2446d765955dSGiuseppe CAVALLARO 		}
2447d765955dSGiuseppe CAVALLARO 	}
2448d765955dSGiuseppe CAVALLARO 
2449d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
24507ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
24517ac6653aSJeff Kirsher 
24527ac6653aSJeff Kirsher 	return IRQ_HANDLED;
24537ac6653aSJeff Kirsher }
24547ac6653aSJeff Kirsher 
24557ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
24567ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2457ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2458ceb69499SGiuseppe CAVALLARO  */
24597ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
24607ac6653aSJeff Kirsher {
24617ac6653aSJeff Kirsher 	disable_irq(dev->irq);
24627ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
24637ac6653aSJeff Kirsher 	enable_irq(dev->irq);
24647ac6653aSJeff Kirsher }
24657ac6653aSJeff Kirsher #endif
24667ac6653aSJeff Kirsher 
24677ac6653aSJeff Kirsher /**
24687ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
24697ac6653aSJeff Kirsher  *  @dev: Device pointer.
24707ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
24717ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
24727ac6653aSJeff Kirsher  *  @cmd: IOCTL command
24737ac6653aSJeff Kirsher  *  Description:
247432ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
24757ac6653aSJeff Kirsher  */
24767ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
24777ac6653aSJeff Kirsher {
24787ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2479891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
24807ac6653aSJeff Kirsher 
24817ac6653aSJeff Kirsher 	if (!netif_running(dev))
24827ac6653aSJeff Kirsher 		return -EINVAL;
24837ac6653aSJeff Kirsher 
2484891434b1SRayagond Kokatanur 	switch (cmd) {
2485891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2486891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2487891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
24887ac6653aSJeff Kirsher 		if (!priv->phydev)
24897ac6653aSJeff Kirsher 			return -EINVAL;
24907ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2491891434b1SRayagond Kokatanur 		break;
2492891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2493891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2494891434b1SRayagond Kokatanur 		break;
2495891434b1SRayagond Kokatanur 	default:
2496891434b1SRayagond Kokatanur 		break;
2497891434b1SRayagond Kokatanur 	}
24987ac6653aSJeff Kirsher 
24997ac6653aSJeff Kirsher 	return ret;
25007ac6653aSJeff Kirsher }
25017ac6653aSJeff Kirsher 
250250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
25037ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
25047ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status;
2505e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap;
25067ac29055SGiuseppe CAVALLARO 
2507c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2508c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
25097ac29055SGiuseppe CAVALLARO {
25107ac29055SGiuseppe CAVALLARO 	int i;
2511c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2512c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
25137ac29055SGiuseppe CAVALLARO 
2514c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2515c24602efSGiuseppe CAVALLARO 		u64 x;
2516c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2517c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2518c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2519c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2520c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2521c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2522c24602efSGiuseppe CAVALLARO 			ep++;
2523c24602efSGiuseppe CAVALLARO 		} else {
2524c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2525c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2526c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2527c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2528c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2529c24602efSGiuseppe CAVALLARO 			p++;
2530c24602efSGiuseppe CAVALLARO 		}
25317ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
25327ac29055SGiuseppe CAVALLARO 	}
2533c24602efSGiuseppe CAVALLARO }
25347ac29055SGiuseppe CAVALLARO 
2535c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2536c24602efSGiuseppe CAVALLARO {
2537c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2538c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2539c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
2540c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
25417ac29055SGiuseppe CAVALLARO 
2542c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2543c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2544c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq);
2545c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2546c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq);
2547c24602efSGiuseppe CAVALLARO 	} else {
2548c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2549c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
2550c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2551c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
25527ac29055SGiuseppe CAVALLARO 	}
25537ac29055SGiuseppe CAVALLARO 
25547ac29055SGiuseppe CAVALLARO 	return 0;
25557ac29055SGiuseppe CAVALLARO }
25567ac29055SGiuseppe CAVALLARO 
25577ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
25587ac29055SGiuseppe CAVALLARO {
25597ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
25607ac29055SGiuseppe CAVALLARO }
25617ac29055SGiuseppe CAVALLARO 
25627ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
25637ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
25647ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
25657ac29055SGiuseppe CAVALLARO 	.read = seq_read,
25667ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
256774863948SDjalal Harouni 	.release = single_release,
25687ac29055SGiuseppe CAVALLARO };
25697ac29055SGiuseppe CAVALLARO 
2570e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2571e7434821SGiuseppe CAVALLARO {
2572e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2573e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2574e7434821SGiuseppe CAVALLARO 
257519e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2576e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2577e7434821SGiuseppe CAVALLARO 		return 0;
2578e7434821SGiuseppe CAVALLARO 	}
2579e7434821SGiuseppe CAVALLARO 
2580e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2581e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2582e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2583e7434821SGiuseppe CAVALLARO 
2584e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2585e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2586e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2587e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2588e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2589e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2590e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2591e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2592e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2593e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2594e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2595e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2596e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2597e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2598e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2599e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2600e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2601e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2602e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2603e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2604e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2605e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2606e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2607e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2608e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2609e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2610e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2611e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2612e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2613e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2614e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2615e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2616e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2617e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2618e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2619e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2620e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2621e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2622e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2623e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2624e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2625e7434821SGiuseppe CAVALLARO 
2626e7434821SGiuseppe CAVALLARO 	return 0;
2627e7434821SGiuseppe CAVALLARO }
2628e7434821SGiuseppe CAVALLARO 
2629e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2630e7434821SGiuseppe CAVALLARO {
2631e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2632e7434821SGiuseppe CAVALLARO }
2633e7434821SGiuseppe CAVALLARO 
2634e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2635e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2636e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2637e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2638e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
263974863948SDjalal Harouni 	.release = single_release,
2640e7434821SGiuseppe CAVALLARO };
2641e7434821SGiuseppe CAVALLARO 
26427ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
26437ac29055SGiuseppe CAVALLARO {
26447ac29055SGiuseppe CAVALLARO 	/* Create debugfs entries */
26457ac29055SGiuseppe CAVALLARO 	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
26467ac29055SGiuseppe CAVALLARO 
26477ac29055SGiuseppe CAVALLARO 	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
26487ac29055SGiuseppe CAVALLARO 		pr_err("ERROR %s, debugfs create directory failed\n",
26497ac29055SGiuseppe CAVALLARO 		       STMMAC_RESOURCE_NAME);
26507ac29055SGiuseppe CAVALLARO 
26517ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
26527ac29055SGiuseppe CAVALLARO 	}
26537ac29055SGiuseppe CAVALLARO 
26547ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
26557ac29055SGiuseppe CAVALLARO 	stmmac_rings_status = debugfs_create_file("descriptors_status",
26567ac29055SGiuseppe CAVALLARO 						  S_IRUGO, stmmac_fs_dir, dev,
26577ac29055SGiuseppe CAVALLARO 						  &stmmac_rings_status_fops);
26587ac29055SGiuseppe CAVALLARO 
26597ac29055SGiuseppe CAVALLARO 	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
26607ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
26617ac29055SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
26627ac29055SGiuseppe CAVALLARO 
26637ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
26647ac29055SGiuseppe CAVALLARO 	}
26657ac29055SGiuseppe CAVALLARO 
2666e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2667e7434821SGiuseppe CAVALLARO 	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
2668e7434821SGiuseppe CAVALLARO 					     dev, &stmmac_dma_cap_fops);
2669e7434821SGiuseppe CAVALLARO 
2670e7434821SGiuseppe CAVALLARO 	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
2671e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2672e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_rings_status);
2673e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
2674e7434821SGiuseppe CAVALLARO 
2675e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2676e7434821SGiuseppe CAVALLARO 	}
2677e7434821SGiuseppe CAVALLARO 
26787ac29055SGiuseppe CAVALLARO 	return 0;
26797ac29055SGiuseppe CAVALLARO }
26807ac29055SGiuseppe CAVALLARO 
26817ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void)
26827ac29055SGiuseppe CAVALLARO {
26837ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_rings_status);
2684e7434821SGiuseppe CAVALLARO 	debugfs_remove(stmmac_dma_cap);
26857ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_fs_dir);
26867ac29055SGiuseppe CAVALLARO }
268750fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
26887ac29055SGiuseppe CAVALLARO 
26897ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
26907ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
26917ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
26927ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
26937ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
26947ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
2695d2afb5bdSGiuseppe CAVALLARO 	.ndo_set_features = stmmac_set_features,
269601789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
26977ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
26987ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
26997ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
27007ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
27017ac6653aSJeff Kirsher #endif
27027ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
27037ac6653aSJeff Kirsher };
27047ac6653aSJeff Kirsher 
27057ac6653aSJeff Kirsher /**
2706cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
270732ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2708732fdf0eSGiuseppe CAVALLARO  *  Description: this function is to configure the MAC device according to
2709732fdf0eSGiuseppe CAVALLARO  *  some platform parameters or the HW capability register. It prepares the
2710732fdf0eSGiuseppe CAVALLARO  *  driver to use either ring or chain modes and to setup either enhanced or
2711732fdf0eSGiuseppe CAVALLARO  *  normal descriptors.
2712cf3f047bSGiuseppe CAVALLARO  */
2713cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2714cf3f047bSGiuseppe CAVALLARO {
2715cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2716cf3f047bSGiuseppe CAVALLARO 
2717cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
271803f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
271903f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
27203b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
27213b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
27223b57de95SVince Bridgers 				      priv->plat->unicast_filter_entries);
272303f2eecdSMarc Kleine-Budde 	} else {
2724cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
272503f2eecdSMarc Kleine-Budde 	}
2726cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2727cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2728cf3f047bSGiuseppe CAVALLARO 
2729cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2730cf3f047bSGiuseppe CAVALLARO 
2731cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2732cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2733cf3f047bSGiuseppe CAVALLARO 
27344a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
27354a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
273629896a67SGiuseppe CAVALLARO 		priv->hw->mode = &chain_mode_ops;
27374a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
27384a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
27394a7d666aSGiuseppe CAVALLARO 	} else {
274029896a67SGiuseppe CAVALLARO 		priv->hw->mode = &ring_mode_ops;
27414a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
27424a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
27434a7d666aSGiuseppe CAVALLARO 	}
27444a7d666aSGiuseppe CAVALLARO 
2745cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2746cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2747cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2748cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2749cf3f047bSGiuseppe CAVALLARO 
2750cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2751cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2752cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2753cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2754cf3f047bSGiuseppe CAVALLARO 		 */
2755cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2756cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
275738912bdbSDeepak SIKRI 
2758dec2165fSSonic Zhang 		/* TXCOE doesn't work in thresh DMA mode */
2759dec2165fSSonic Zhang 		if (priv->plat->force_thresh_dma_mode)
2760dec2165fSSonic Zhang 			priv->plat->tx_coe = 0;
2761dec2165fSSonic Zhang 		else
276238912bdbSDeepak SIKRI 			priv->plat->tx_coe = priv->dma_cap.tx_coe;
276338912bdbSDeepak SIKRI 
276438912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
276538912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
276638912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
276738912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
276838912bdbSDeepak SIKRI 
2769cf3f047bSGiuseppe CAVALLARO 	} else
2770cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2771cf3f047bSGiuseppe CAVALLARO 
277261369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
277361369d02SByungho An 	stmmac_selec_desc_mode(priv);
277461369d02SByungho An 
2775d2afb5bdSGiuseppe CAVALLARO 	if (priv->plat->rx_coe) {
2776d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
277738912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
277838912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2779d2afb5bdSGiuseppe CAVALLARO 	}
2780cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2781cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2782cf3f047bSGiuseppe CAVALLARO 
2783cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2784cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2785cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2786cf3f047bSGiuseppe CAVALLARO 	}
2787cf3f047bSGiuseppe CAVALLARO 
2788c24602efSGiuseppe CAVALLARO 	return 0;
2789cf3f047bSGiuseppe CAVALLARO }
2790cf3f047bSGiuseppe CAVALLARO 
2791cf3f047bSGiuseppe CAVALLARO /**
2792bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2793bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2794ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2795ff3dd78cSGiuseppe CAVALLARO  * @addr: iobase memory address
2796bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2797bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
27987ac6653aSJeff Kirsher  */
2799bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device,
2800cf3f047bSGiuseppe CAVALLARO 				     struct plat_stmmacenet_data *plat_dat,
2801cf3f047bSGiuseppe CAVALLARO 				     void __iomem *addr)
28027ac6653aSJeff Kirsher {
28037ac6653aSJeff Kirsher 	int ret = 0;
2804bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2805bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
28067ac6653aSJeff Kirsher 
2807bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
280841de8d4cSJoe Perches 	if (!ndev)
2809bfab27a1SGiuseppe CAVALLARO 		return NULL;
28107ac6653aSJeff Kirsher 
2811bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
28127ac6653aSJeff Kirsher 
2813bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2814bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2815bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2816bfab27a1SGiuseppe CAVALLARO 
2817bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2818cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2819cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2820cf3f047bSGiuseppe CAVALLARO 	priv->ioaddr = addr;
2821cf3f047bSGiuseppe CAVALLARO 	priv->dev->base_addr = (unsigned long)addr;
2822bfab27a1SGiuseppe CAVALLARO 
2823cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2824cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2825cf3f047bSGiuseppe CAVALLARO 
2826cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2827ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2828ceb69499SGiuseppe CAVALLARO 	 */
2829cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2830cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2831cf3f047bSGiuseppe CAVALLARO 
283262866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
283362866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
283462866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
283562866e98SChen-Yu Tsai 			 __func__);
2836c5bb86c3SKweh, Hock Leong 		/* If failed to obtain stmmac_clk and specific clk_csr value
2837c5bb86c3SKweh, Hock Leong 		 * is NOT passed from the platform, probe fail.
2838c5bb86c3SKweh, Hock Leong 		 */
2839c5bb86c3SKweh, Hock Leong 		if (!priv->plat->clk_csr) {
2840c5e4ddbdSChen-Yu Tsai 			ret = PTR_ERR(priv->stmmac_clk);
284162866e98SChen-Yu Tsai 			goto error_clk_get;
2842c5bb86c3SKweh, Hock Leong 		} else {
2843c5bb86c3SKweh, Hock Leong 			priv->stmmac_clk = NULL;
2844c5bb86c3SKweh, Hock Leong 		}
284562866e98SChen-Yu Tsai 	}
284662866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
284762866e98SChen-Yu Tsai 
2848c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2849c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2850c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2851c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2852c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2853c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2854c5e4ddbdSChen-Yu Tsai 		}
2855c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2856c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2857c5e4ddbdSChen-Yu Tsai 	}
2858c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2859c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2860c5e4ddbdSChen-Yu Tsai 
2861cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2862c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2863c24602efSGiuseppe CAVALLARO 	if (ret)
286462866e98SChen-Yu Tsai 		goto error_hw_init;
2865cf3f047bSGiuseppe CAVALLARO 
2866cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2867cf3f047bSGiuseppe CAVALLARO 
2868cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2869cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2870bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2871bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
28727ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
28737ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2874f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
28757ac6653aSJeff Kirsher #endif
28767ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
28777ac6653aSJeff Kirsher 
28787ac6653aSJeff Kirsher 	if (flow_ctrl)
28797ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
28807ac6653aSJeff Kirsher 
288162a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
288262a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
288362a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
288462a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
288562a2ab93SGiuseppe CAVALLARO 	 */
288662a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
288762a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
288862a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
288962a2ab93SGiuseppe CAVALLARO 	}
289062a2ab93SGiuseppe CAVALLARO 
2891bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
28927ac6653aSJeff Kirsher 
28937ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
2894a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
28957ac6653aSJeff Kirsher 
2896bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
28977ac6653aSJeff Kirsher 	if (ret) {
2898cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
28996a81c26fSViresh Kumar 		goto error_netdev_register;
29007ac6653aSJeff Kirsher 	}
29017ac6653aSJeff Kirsher 
2902cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
2903cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
2904cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
2905cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
2906cd7201f4SGiuseppe CAVALLARO 	 * clock input.
2907cd7201f4SGiuseppe CAVALLARO 	 */
2908cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
2909cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
2910cd7201f4SGiuseppe CAVALLARO 	else
2911cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
2912cd7201f4SGiuseppe CAVALLARO 
2913e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
2914e58bb43fSGiuseppe CAVALLARO 
29154d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
29164d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
29174bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
29184bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
29194bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
29204bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
29214bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
29226a81c26fSViresh Kumar 			goto error_mdio_register;
29234bfcbd7aSFrancesco Virlinzi 		}
2924e58bb43fSGiuseppe CAVALLARO 	}
29254bfcbd7aSFrancesco Virlinzi 
2926bfab27a1SGiuseppe CAVALLARO 	return priv;
29277ac6653aSJeff Kirsher 
29286a81c26fSViresh Kumar error_mdio_register:
29297ac6653aSJeff Kirsher 	unregister_netdev(ndev);
29306a81c26fSViresh Kumar error_netdev_register:
29316a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
293262866e98SChen-Yu Tsai error_hw_init:
293362866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
293462866e98SChen-Yu Tsai error_clk_get:
29357ac6653aSJeff Kirsher 	free_netdev(ndev);
29367ac6653aSJeff Kirsher 
2937c5e4ddbdSChen-Yu Tsai 	return ERR_PTR(ret);
29387ac6653aSJeff Kirsher }
2939b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
29407ac6653aSJeff Kirsher 
29417ac6653aSJeff Kirsher /**
29427ac6653aSJeff Kirsher  * stmmac_dvr_remove
2943bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
29447ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
2945bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
29467ac6653aSJeff Kirsher  */
2947bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
29487ac6653aSJeff Kirsher {
29497ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
29507ac6653aSJeff Kirsher 
29517ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
29527ac6653aSJeff Kirsher 
29537ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
29547ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
29557ac6653aSJeff Kirsher 
2956bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
29574d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
29584d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI)
29594bfcbd7aSFrancesco Virlinzi 		stmmac_mdio_unregister(ndev);
29607ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
29617ac6653aSJeff Kirsher 	unregister_netdev(ndev);
2962c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2963c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
296462866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
29657ac6653aSJeff Kirsher 	free_netdev(ndev);
29667ac6653aSJeff Kirsher 
29677ac6653aSJeff Kirsher 	return 0;
29687ac6653aSJeff Kirsher }
2969b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
29707ac6653aSJeff Kirsher 
2971732fdf0eSGiuseppe CAVALLARO /**
2972732fdf0eSGiuseppe CAVALLARO  * stmmac_suspend - suspend callback
2973732fdf0eSGiuseppe CAVALLARO  * @ndev: net device pointer
2974732fdf0eSGiuseppe CAVALLARO  * Description: this is the function to suspend the device and it is called
2975732fdf0eSGiuseppe CAVALLARO  * by the platform driver to stop the network queue, release the resources,
2976732fdf0eSGiuseppe CAVALLARO  * program the PMT register (for WoL), clean and release driver resources.
2977732fdf0eSGiuseppe CAVALLARO  */
2978bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
29797ac6653aSJeff Kirsher {
29807ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2981f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
29827ac6653aSJeff Kirsher 
29837ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
29847ac6653aSJeff Kirsher 		return 0;
29857ac6653aSJeff Kirsher 
2986102463b1SFrancesco Virlinzi 	if (priv->phydev)
2987102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
2988102463b1SFrancesco Virlinzi 
2989f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
29907ac6653aSJeff Kirsher 
29917ac6653aSJeff Kirsher 	netif_device_detach(ndev);
29927ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
29937ac6653aSJeff Kirsher 
29947ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
29957ac6653aSJeff Kirsher 
29967ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
29977ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
29987ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
2999c24602efSGiuseppe CAVALLARO 
3000c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
30017ac6653aSJeff Kirsher 
30027ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
300389f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
30047ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
300589f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
300689f7f2cfSSrinivas Kandagatla 	} else {
3007bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
3008db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
3009ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
3010777da230SGiuseppe CAVALLARO 		clk_disable(priv->stmmac_clk);
3011ba1377ffSGiuseppe CAVALLARO 	}
3012f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
30132d871aa0SVince Bridgers 
30142d871aa0SVince Bridgers 	priv->oldlink = 0;
30152d871aa0SVince Bridgers 	priv->speed = 0;
30162d871aa0SVince Bridgers 	priv->oldduplex = -1;
30177ac6653aSJeff Kirsher 	return 0;
30187ac6653aSJeff Kirsher }
3019b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend);
30207ac6653aSJeff Kirsher 
3021732fdf0eSGiuseppe CAVALLARO /**
3022732fdf0eSGiuseppe CAVALLARO  * stmmac_resume - resume callback
3023732fdf0eSGiuseppe CAVALLARO  * @ndev: net device pointer
3024732fdf0eSGiuseppe CAVALLARO  * Description: when resume this function is invoked to setup the DMA and CORE
3025732fdf0eSGiuseppe CAVALLARO  * in a usable state.
3026732fdf0eSGiuseppe CAVALLARO  */
3027bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
30287ac6653aSJeff Kirsher {
30297ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3030f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
30317ac6653aSJeff Kirsher 
30327ac6653aSJeff Kirsher 	if (!netif_running(ndev))
30337ac6653aSJeff Kirsher 		return 0;
30347ac6653aSJeff Kirsher 
3035f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
30367ac6653aSJeff Kirsher 
30377ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
30387ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
30397ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
30407ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
3041ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
3042ceb69499SGiuseppe CAVALLARO 	 */
3043623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
30447ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
304589f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
3046623997fbSSrinivas Kandagatla 	} else {
3047db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
3048ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
3049777da230SGiuseppe CAVALLARO 		clk_enable(priv->stmmac_clk);
3050623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
3051623997fbSSrinivas Kandagatla 		if (priv->mii)
3052623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
3053623997fbSSrinivas Kandagatla 	}
30547ac6653aSJeff Kirsher 
30557ac6653aSJeff Kirsher 	netif_device_attach(ndev);
30567ac6653aSJeff Kirsher 
3057777da230SGiuseppe CAVALLARO 	init_dma_desc_rings(ndev, GFP_ATOMIC);
3058fe131929SHuacai Chen 	stmmac_hw_setup(ndev, false);
3059777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
30607ac6653aSJeff Kirsher 
30617ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
30627ac6653aSJeff Kirsher 
30637ac6653aSJeff Kirsher 	netif_start_queue(ndev);
30647ac6653aSJeff Kirsher 
3065f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
3066102463b1SFrancesco Virlinzi 
3067102463b1SFrancesco Virlinzi 	if (priv->phydev)
3068102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
3069102463b1SFrancesco Virlinzi 
30707ac6653aSJeff Kirsher 	return 0;
30717ac6653aSJeff Kirsher }
3072b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume);
3073ba27ec66SGiuseppe CAVALLARO 
30747ac6653aSJeff Kirsher #ifndef MODULE
30757ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
30767ac6653aSJeff Kirsher {
30777ac6653aSJeff Kirsher 	char *opt;
30787ac6653aSJeff Kirsher 
30797ac6653aSJeff Kirsher 	if (!str || !*str)
30807ac6653aSJeff Kirsher 		return -EINVAL;
30817ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
30827ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
3083ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
30847ac6653aSJeff Kirsher 				goto err;
30857ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
3086ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
30877ac6653aSJeff Kirsher 				goto err;
30887ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
3089ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_txsize))
30907ac6653aSJeff Kirsher 				goto err;
30917ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
3092ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_rxsize))
30937ac6653aSJeff Kirsher 				goto err;
30947ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
3095ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
30967ac6653aSJeff Kirsher 				goto err;
30977ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
3098ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
30997ac6653aSJeff Kirsher 				goto err;
31007ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3101ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
31027ac6653aSJeff Kirsher 				goto err;
31037ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3104ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
31057ac6653aSJeff Kirsher 				goto err;
31067ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3107ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
31087ac6653aSJeff Kirsher 				goto err;
3109506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3110d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3111d765955dSGiuseppe CAVALLARO 				goto err;
31124a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
31134a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
31144a7d666aSGiuseppe CAVALLARO 				goto err;
31157ac6653aSJeff Kirsher 		}
31167ac6653aSJeff Kirsher 	}
31177ac6653aSJeff Kirsher 	return 0;
31187ac6653aSJeff Kirsher 
31197ac6653aSJeff Kirsher err:
31207ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
31217ac6653aSJeff Kirsher 	return -EINVAL;
31227ac6653aSJeff Kirsher }
31237ac6653aSJeff Kirsher 
31247ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3125ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
31266fc0d0f2SGiuseppe Cavallaro 
31276fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
31286fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
31296fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3130