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>
555790cf3cSMathieu Olivari #include <linux/of_mdio.h>
5619d857c9SPhil Reid #include "dwmac1000.h"
577ac6653aSJeff Kirsher 
587ac6653aSJeff Kirsher #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
597ac6653aSJeff Kirsher 
607ac6653aSJeff Kirsher /* Module parameters */
6132ceabcaSGiuseppe CAVALLARO #define TX_TIMEO	5000
627ac6653aSJeff Kirsher static int watchdog = TX_TIMEO;
637ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR);
6432ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)");
657ac6653aSJeff Kirsher 
6632ceabcaSGiuseppe CAVALLARO static int debug = -1;
677ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR);
6832ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
697ac6653aSJeff Kirsher 
7047d1f71fSstephen hemminger static int phyaddr = -1;
717ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO);
727ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address");
737ac6653aSJeff Kirsher 
74e3ad57c9SGiuseppe Cavallaro #define STMMAC_TX_THRESH	(DMA_TX_SIZE / 4)
75120e87f9SGiuseppe Cavallaro #define STMMAC_RX_THRESH	(DMA_RX_SIZE / 4)
767ac6653aSJeff Kirsher 
777ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF;
787ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR);
797ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]");
807ac6653aSJeff Kirsher 
817ac6653aSJeff Kirsher static int pause = PAUSE_TIME;
827ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR);
837ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time");
847ac6653aSJeff Kirsher 
857ac6653aSJeff Kirsher #define TC_DEFAULT 64
867ac6653aSJeff Kirsher static int tc = TC_DEFAULT;
877ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR);
887ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value");
897ac6653aSJeff Kirsher 
90d916701cSGiuseppe CAVALLARO #define	DEFAULT_BUFSIZE	1536
91d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE;
927ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR);
937ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size");
947ac6653aSJeff Kirsher 
9522ad3838SGiuseppe Cavallaro #define	STMMAC_RX_COPYBREAK	256
9622ad3838SGiuseppe Cavallaro 
977ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
987ac6653aSJeff Kirsher 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
997ac6653aSJeff Kirsher 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
1007ac6653aSJeff Kirsher 
101d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER	1000
102d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
103d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR);
104d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
105f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
106d765955dSGiuseppe CAVALLARO 
1074a7d666aSGiuseppe CAVALLARO /* By default the driver will use the ring mode to manage tx and rx descriptors
1084a7d666aSGiuseppe CAVALLARO  * but passing this value so user can force to use the chain instead of the ring
1094a7d666aSGiuseppe CAVALLARO  */
1104a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode;
1114a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO);
1124a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
1134a7d666aSGiuseppe CAVALLARO 
1147ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
1157ac6653aSJeff Kirsher 
11650fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
117bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev);
118466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev);
119bfab27a1SGiuseppe CAVALLARO #endif
120bfab27a1SGiuseppe CAVALLARO 
1219125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
1229125cdd1SGiuseppe CAVALLARO 
1237ac6653aSJeff Kirsher /**
1247ac6653aSJeff Kirsher  * stmmac_verify_args - verify the driver parameters.
125732fdf0eSGiuseppe CAVALLARO  * Description: it checks the driver parameters and set a default in case of
126732fdf0eSGiuseppe CAVALLARO  * errors.
1277ac6653aSJeff Kirsher  */
1287ac6653aSJeff Kirsher static void stmmac_verify_args(void)
1297ac6653aSJeff Kirsher {
1307ac6653aSJeff Kirsher 	if (unlikely(watchdog < 0))
1317ac6653aSJeff Kirsher 		watchdog = TX_TIMEO;
132d916701cSGiuseppe CAVALLARO 	if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
133d916701cSGiuseppe CAVALLARO 		buf_sz = DEFAULT_BUFSIZE;
1347ac6653aSJeff Kirsher 	if (unlikely(flow_ctrl > 1))
1357ac6653aSJeff Kirsher 		flow_ctrl = FLOW_AUTO;
1367ac6653aSJeff Kirsher 	else if (likely(flow_ctrl < 0))
1377ac6653aSJeff Kirsher 		flow_ctrl = FLOW_OFF;
1387ac6653aSJeff Kirsher 	if (unlikely((pause < 0) || (pause > 0xffff)))
1397ac6653aSJeff Kirsher 		pause = PAUSE_TIME;
140d765955dSGiuseppe CAVALLARO 	if (eee_timer < 0)
141d765955dSGiuseppe CAVALLARO 		eee_timer = STMMAC_DEFAULT_LPI_TIMER;
1427ac6653aSJeff Kirsher }
1437ac6653aSJeff Kirsher 
14432ceabcaSGiuseppe CAVALLARO /**
14532ceabcaSGiuseppe CAVALLARO  * stmmac_clk_csr_set - dynamically set the MDC clock
14632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
14732ceabcaSGiuseppe CAVALLARO  * Description: this is to dynamically set the MDC clock according to the csr
14832ceabcaSGiuseppe CAVALLARO  * clock input.
14932ceabcaSGiuseppe CAVALLARO  * Note:
15032ceabcaSGiuseppe CAVALLARO  *	If a specific clk_csr value is passed from the platform
15132ceabcaSGiuseppe CAVALLARO  *	this means that the CSR Clock Range selection cannot be
15232ceabcaSGiuseppe CAVALLARO  *	changed at run-time and it is fixed (as reported in the driver
15332ceabcaSGiuseppe CAVALLARO  *	documentation). Viceversa the driver will try to set the MDC
15432ceabcaSGiuseppe CAVALLARO  *	clock dynamically according to the actual clock input.
15532ceabcaSGiuseppe CAVALLARO  */
156cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv)
157cd7201f4SGiuseppe CAVALLARO {
158cd7201f4SGiuseppe CAVALLARO 	u32 clk_rate;
159cd7201f4SGiuseppe CAVALLARO 
160cd7201f4SGiuseppe CAVALLARO 	clk_rate = clk_get_rate(priv->stmmac_clk);
161cd7201f4SGiuseppe CAVALLARO 
162cd7201f4SGiuseppe CAVALLARO 	/* Platform provided default clk_csr would be assumed valid
163ceb69499SGiuseppe CAVALLARO 	 * for all other cases except for the below mentioned ones.
164ceb69499SGiuseppe CAVALLARO 	 * For values higher than the IEEE 802.3 specified frequency
165ceb69499SGiuseppe CAVALLARO 	 * we can not estimate the proper divider as it is not known
166ceb69499SGiuseppe CAVALLARO 	 * the frequency of clk_csr_i. So we do not change the default
167ceb69499SGiuseppe CAVALLARO 	 * divider.
168ceb69499SGiuseppe CAVALLARO 	 */
169cd7201f4SGiuseppe CAVALLARO 	if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
170cd7201f4SGiuseppe CAVALLARO 		if (clk_rate < CSR_F_35M)
171cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_20_35M;
172cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
173cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_35_60M;
174cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
175cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_60_100M;
176cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
177cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_100_150M;
178cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
179cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_150_250M;
18019d857c9SPhil Reid 		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
181cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_250_300M;
182ceb69499SGiuseppe CAVALLARO 	}
183cd7201f4SGiuseppe CAVALLARO }
184cd7201f4SGiuseppe CAVALLARO 
1857ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len)
1867ac6653aSJeff Kirsher {
187424c4f78SAndy Shevchenko 	pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf);
188424c4f78SAndy Shevchenko 	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
1897ac6653aSJeff Kirsher }
1907ac6653aSJeff Kirsher 
1917ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
1927ac6653aSJeff Kirsher {
193e3ad57c9SGiuseppe Cavallaro 	unsigned avail;
194e3ad57c9SGiuseppe Cavallaro 
195e3ad57c9SGiuseppe Cavallaro 	if (priv->dirty_tx > priv->cur_tx)
196e3ad57c9SGiuseppe Cavallaro 		avail = priv->dirty_tx - priv->cur_tx - 1;
197e3ad57c9SGiuseppe Cavallaro 	else
198e3ad57c9SGiuseppe Cavallaro 		avail = DMA_TX_SIZE - priv->cur_tx + priv->dirty_tx - 1;
199e3ad57c9SGiuseppe Cavallaro 
200e3ad57c9SGiuseppe Cavallaro 	return avail;
201e3ad57c9SGiuseppe Cavallaro }
202e3ad57c9SGiuseppe Cavallaro 
203e3ad57c9SGiuseppe Cavallaro static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv)
204e3ad57c9SGiuseppe Cavallaro {
205e3ad57c9SGiuseppe Cavallaro 	unsigned dirty;
206e3ad57c9SGiuseppe Cavallaro 
207e3ad57c9SGiuseppe Cavallaro 	if (priv->dirty_rx <= priv->cur_rx)
208e3ad57c9SGiuseppe Cavallaro 		dirty = priv->cur_rx - priv->dirty_rx;
209e3ad57c9SGiuseppe Cavallaro 	else
210e3ad57c9SGiuseppe Cavallaro 		dirty = DMA_RX_SIZE - priv->dirty_rx + priv->cur_rx;
211e3ad57c9SGiuseppe Cavallaro 
212e3ad57c9SGiuseppe Cavallaro 	return dirty;
2137ac6653aSJeff Kirsher }
2147ac6653aSJeff Kirsher 
21532ceabcaSGiuseppe CAVALLARO /**
216732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed - callback for speed selection
21732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
21832ceabcaSGiuseppe CAVALLARO  * Description: on some platforms (e.g. ST), some HW system configuraton
21932ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2207ac6653aSJeff Kirsher  */
2217ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2227ac6653aSJeff Kirsher {
2237ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
2247ac6653aSJeff Kirsher 
2257ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
226ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2277ac6653aSJeff Kirsher }
2287ac6653aSJeff Kirsher 
22932ceabcaSGiuseppe CAVALLARO /**
230732fdf0eSGiuseppe CAVALLARO  * stmmac_enable_eee_mode - check and enter in LPI mode
23132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
232732fdf0eSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode in case of
233732fdf0eSGiuseppe CAVALLARO  * EEE.
23432ceabcaSGiuseppe CAVALLARO  */
235d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
236d765955dSGiuseppe CAVALLARO {
237d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
238d765955dSGiuseppe CAVALLARO 	if ((priv->dirty_tx == priv->cur_tx) &&
239d765955dSGiuseppe CAVALLARO 	    (priv->tx_path_in_lpi_mode == false))
2407ed24bbeSVince Bridgers 		priv->hw->mac->set_eee_mode(priv->hw);
241d765955dSGiuseppe CAVALLARO }
242d765955dSGiuseppe CAVALLARO 
24332ceabcaSGiuseppe CAVALLARO /**
244732fdf0eSGiuseppe CAVALLARO  * stmmac_disable_eee_mode - disable and exit from LPI mode
24532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
24632ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
24732ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
24832ceabcaSGiuseppe CAVALLARO  */
249d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
250d765955dSGiuseppe CAVALLARO {
2517ed24bbeSVince Bridgers 	priv->hw->mac->reset_eee_mode(priv->hw);
252d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
253d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
254d765955dSGiuseppe CAVALLARO }
255d765955dSGiuseppe CAVALLARO 
256d765955dSGiuseppe CAVALLARO /**
257732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer - EEE TX SW timer.
258d765955dSGiuseppe CAVALLARO  * @arg : data hook
259d765955dSGiuseppe CAVALLARO  * Description:
26032ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
261d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
262d765955dSGiuseppe CAVALLARO  */
263d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
264d765955dSGiuseppe CAVALLARO {
265d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
266d765955dSGiuseppe CAVALLARO 
267d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
268f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
269d765955dSGiuseppe CAVALLARO }
270d765955dSGiuseppe CAVALLARO 
271d765955dSGiuseppe CAVALLARO /**
272732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_init - init EEE
27332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
274d765955dSGiuseppe CAVALLARO  * Description:
275732fdf0eSGiuseppe CAVALLARO  *  if the GMAC supports the EEE (from the HW cap reg) and the phy device
276732fdf0eSGiuseppe CAVALLARO  *  can also manage EEE, this function enable the LPI state and start related
277732fdf0eSGiuseppe CAVALLARO  *  timer.
278d765955dSGiuseppe CAVALLARO  */
279d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
280d765955dSGiuseppe CAVALLARO {
2814741cf9cSGiuseppe CAVALLARO 	unsigned long flags;
282d765955dSGiuseppe CAVALLARO 	bool ret = false;
283d765955dSGiuseppe CAVALLARO 
284f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
285f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
286f5351ef7SGiuseppe CAVALLARO 	 */
287f5351ef7SGiuseppe CAVALLARO 	if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
288f5351ef7SGiuseppe CAVALLARO 	    (priv->pcs == STMMAC_PCS_RTBI))
289f5351ef7SGiuseppe CAVALLARO 		goto out;
290f5351ef7SGiuseppe CAVALLARO 
291d765955dSGiuseppe CAVALLARO 	/* MAC core supports the EEE feature. */
292d765955dSGiuseppe CAVALLARO 	if (priv->dma_cap.eee) {
29383bf79b6SGiuseppe CAVALLARO 		int tx_lpi_timer = priv->tx_lpi_timer;
294d765955dSGiuseppe CAVALLARO 
29583bf79b6SGiuseppe CAVALLARO 		/* Check if the PHY supports EEE */
29683bf79b6SGiuseppe CAVALLARO 		if (phy_init_eee(priv->phydev, 1)) {
29783bf79b6SGiuseppe CAVALLARO 			/* To manage at run-time if the EEE cannot be supported
29883bf79b6SGiuseppe CAVALLARO 			 * anymore (for example because the lp caps have been
29983bf79b6SGiuseppe CAVALLARO 			 * changed).
30083bf79b6SGiuseppe CAVALLARO 			 * In that case the driver disable own timers.
30183bf79b6SGiuseppe CAVALLARO 			 */
3024741cf9cSGiuseppe CAVALLARO 			spin_lock_irqsave(&priv->lock, flags);
30383bf79b6SGiuseppe CAVALLARO 			if (priv->eee_active) {
30483bf79b6SGiuseppe CAVALLARO 				pr_debug("stmmac: disable EEE\n");
30583bf79b6SGiuseppe CAVALLARO 				del_timer_sync(&priv->eee_ctrl_timer);
3067ed24bbeSVince Bridgers 				priv->hw->mac->set_eee_timer(priv->hw, 0,
30783bf79b6SGiuseppe CAVALLARO 							     tx_lpi_timer);
30883bf79b6SGiuseppe CAVALLARO 			}
30983bf79b6SGiuseppe CAVALLARO 			priv->eee_active = 0;
3104741cf9cSGiuseppe CAVALLARO 			spin_unlock_irqrestore(&priv->lock, flags);
31183bf79b6SGiuseppe CAVALLARO 			goto out;
31283bf79b6SGiuseppe CAVALLARO 		}
31383bf79b6SGiuseppe CAVALLARO 		/* Activate the EEE and start timers */
3144741cf9cSGiuseppe CAVALLARO 		spin_lock_irqsave(&priv->lock, flags);
315f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
316d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
317ccb36da1SVaishali Thakkar 			setup_timer(&priv->eee_ctrl_timer,
318ccb36da1SVaishali Thakkar 				    stmmac_eee_ctrl_timer,
319ccb36da1SVaishali Thakkar 				    (unsigned long)priv);
320ccb36da1SVaishali Thakkar 			mod_timer(&priv->eee_ctrl_timer,
321ccb36da1SVaishali Thakkar 				  STMMAC_LPI_T(eee_timer));
322d765955dSGiuseppe CAVALLARO 
3237ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_timer(priv->hw,
324f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
32583bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
32671965352SGiuseppe CAVALLARO 		}
327f5351ef7SGiuseppe CAVALLARO 		/* Set HW EEE according to the speed */
32871965352SGiuseppe CAVALLARO 		priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
329d765955dSGiuseppe CAVALLARO 
330d765955dSGiuseppe CAVALLARO 		ret = true;
3314741cf9cSGiuseppe CAVALLARO 		spin_unlock_irqrestore(&priv->lock, flags);
3324741cf9cSGiuseppe CAVALLARO 
3334741cf9cSGiuseppe CAVALLARO 		pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
334d765955dSGiuseppe CAVALLARO 	}
335d765955dSGiuseppe CAVALLARO out:
336d765955dSGiuseppe CAVALLARO 	return ret;
337d765955dSGiuseppe CAVALLARO }
338d765955dSGiuseppe CAVALLARO 
339732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps
34032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
341891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
342891434b1SRayagond Kokatanur  * @skb : the socket buffer
343891434b1SRayagond Kokatanur  * Description :
344891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
345891434b1SRayagond Kokatanur  * and also perform some sanity checks.
346891434b1SRayagond Kokatanur  */
347891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
348ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
349891434b1SRayagond Kokatanur {
350891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
351891434b1SRayagond Kokatanur 	u64 ns;
352891434b1SRayagond Kokatanur 	void *desc = NULL;
353891434b1SRayagond Kokatanur 
354891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
355891434b1SRayagond Kokatanur 		return;
356891434b1SRayagond Kokatanur 
357ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
35875e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
359891434b1SRayagond Kokatanur 		return;
360891434b1SRayagond Kokatanur 
361891434b1SRayagond Kokatanur 	if (priv->adv_ts)
362891434b1SRayagond Kokatanur 		desc = (priv->dma_etx + entry);
363891434b1SRayagond Kokatanur 	else
364891434b1SRayagond Kokatanur 		desc = (priv->dma_tx + entry);
365891434b1SRayagond Kokatanur 
366891434b1SRayagond Kokatanur 	/* check tx tstamp status */
367891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
368891434b1SRayagond Kokatanur 		return;
369891434b1SRayagond Kokatanur 
370891434b1SRayagond Kokatanur 	/* get the valid tstamp */
371891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
372891434b1SRayagond Kokatanur 
373891434b1SRayagond Kokatanur 	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
374891434b1SRayagond Kokatanur 	shhwtstamp.hwtstamp = ns_to_ktime(ns);
375891434b1SRayagond Kokatanur 	/* pass tstamp to stack */
376891434b1SRayagond Kokatanur 	skb_tstamp_tx(skb, &shhwtstamp);
377891434b1SRayagond Kokatanur 
378891434b1SRayagond Kokatanur 	return;
379891434b1SRayagond Kokatanur }
380891434b1SRayagond Kokatanur 
381732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps
38232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
383891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
384891434b1SRayagond Kokatanur  * @skb : the socket buffer
385891434b1SRayagond Kokatanur  * Description :
386891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
387891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
388891434b1SRayagond Kokatanur  */
389891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
390ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
391891434b1SRayagond Kokatanur {
392891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
393891434b1SRayagond Kokatanur 	u64 ns;
394891434b1SRayagond Kokatanur 	void *desc = NULL;
395891434b1SRayagond Kokatanur 
396891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
397891434b1SRayagond Kokatanur 		return;
398891434b1SRayagond Kokatanur 
399891434b1SRayagond Kokatanur 	if (priv->adv_ts)
400891434b1SRayagond Kokatanur 		desc = (priv->dma_erx + entry);
401891434b1SRayagond Kokatanur 	else
402891434b1SRayagond Kokatanur 		desc = (priv->dma_rx + entry);
403891434b1SRayagond Kokatanur 
404ceb69499SGiuseppe CAVALLARO 	/* exit if rx tstamp is not valid */
405891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
406891434b1SRayagond Kokatanur 		return;
407891434b1SRayagond Kokatanur 
408891434b1SRayagond Kokatanur 	/* get valid tstamp */
409891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
410891434b1SRayagond Kokatanur 	shhwtstamp = skb_hwtstamps(skb);
411891434b1SRayagond Kokatanur 	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
412891434b1SRayagond Kokatanur 	shhwtstamp->hwtstamp = ns_to_ktime(ns);
413891434b1SRayagond Kokatanur }
414891434b1SRayagond Kokatanur 
415891434b1SRayagond Kokatanur /**
416891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
417891434b1SRayagond Kokatanur  *  @dev: device pointer.
418891434b1SRayagond Kokatanur  *  @ifr: An IOCTL specefic structure, that can contain a pointer to
419891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
420891434b1SRayagond Kokatanur  *  Description:
421891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
422891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
423891434b1SRayagond Kokatanur  *  Return Value:
424891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
425891434b1SRayagond Kokatanur  */
426891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
427891434b1SRayagond Kokatanur {
428891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
429891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
4300a624155SArnd Bergmann 	struct timespec64 now;
431891434b1SRayagond Kokatanur 	u64 temp = 0;
432891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
433891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
434891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
435891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
436891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
437891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
438891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
439891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
440891434b1SRayagond Kokatanur 	u32 value = 0;
44119d857c9SPhil Reid 	u32 sec_inc;
442891434b1SRayagond Kokatanur 
443891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
444891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
445891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
446891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
447891434b1SRayagond Kokatanur 
448891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
449891434b1SRayagond Kokatanur 	}
450891434b1SRayagond Kokatanur 
451891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
452891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
453891434b1SRayagond Kokatanur 		return -EFAULT;
454891434b1SRayagond Kokatanur 
455891434b1SRayagond Kokatanur 	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
456891434b1SRayagond Kokatanur 		 __func__, config.flags, config.tx_type, config.rx_filter);
457891434b1SRayagond Kokatanur 
458891434b1SRayagond Kokatanur 	/* reserved for future extensions */
459891434b1SRayagond Kokatanur 	if (config.flags)
460891434b1SRayagond Kokatanur 		return -EINVAL;
461891434b1SRayagond Kokatanur 
4625f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4635f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
464891434b1SRayagond Kokatanur 		return -ERANGE;
465891434b1SRayagond Kokatanur 
466891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
467891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
468891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
469ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
470891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
471891434b1SRayagond Kokatanur 			break;
472891434b1SRayagond Kokatanur 
473891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
474ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
475891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
476891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
477891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
478891434b1SRayagond Kokatanur 
479891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
480891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
481891434b1SRayagond Kokatanur 			break;
482891434b1SRayagond Kokatanur 
483891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
484ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
485891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
486891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
487891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
488891434b1SRayagond Kokatanur 
489891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
490891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
491891434b1SRayagond Kokatanur 			break;
492891434b1SRayagond Kokatanur 
493891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
494ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
495891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
496891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
497891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
498891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
499891434b1SRayagond Kokatanur 
500891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
501891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
502891434b1SRayagond Kokatanur 			break;
503891434b1SRayagond Kokatanur 
504891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
505ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
506891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
507891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
508891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
509891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
510891434b1SRayagond Kokatanur 
511891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
512891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
513891434b1SRayagond Kokatanur 			break;
514891434b1SRayagond Kokatanur 
515891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
516ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
517891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
518891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
519891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
520891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
521891434b1SRayagond Kokatanur 
522891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
523891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
524891434b1SRayagond Kokatanur 			break;
525891434b1SRayagond Kokatanur 
526891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
527ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
528891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
529891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
530891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
531891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
532891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
533891434b1SRayagond Kokatanur 
534891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
535891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
536891434b1SRayagond Kokatanur 			break;
537891434b1SRayagond Kokatanur 
538891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
539ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
540891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
541891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
542891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
543891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
544891434b1SRayagond Kokatanur 
545891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
546891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
547891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
548891434b1SRayagond Kokatanur 			break;
549891434b1SRayagond Kokatanur 
550891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
551ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
552891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
553891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
554891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
555891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
556891434b1SRayagond Kokatanur 
557891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
558891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
559891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
560891434b1SRayagond Kokatanur 			break;
561891434b1SRayagond Kokatanur 
562891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
563ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
564891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
565891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
566891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
567891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
568891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
569891434b1SRayagond Kokatanur 
570891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
571891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
572891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
573891434b1SRayagond Kokatanur 			break;
574891434b1SRayagond Kokatanur 
575891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
576ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
577891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
578891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
579891434b1SRayagond Kokatanur 			break;
580891434b1SRayagond Kokatanur 
581891434b1SRayagond Kokatanur 		default:
582891434b1SRayagond Kokatanur 			return -ERANGE;
583891434b1SRayagond Kokatanur 		}
584891434b1SRayagond Kokatanur 	} else {
585891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
586891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
587891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
588891434b1SRayagond Kokatanur 			break;
589891434b1SRayagond Kokatanur 		default:
590891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
591891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
592891434b1SRayagond Kokatanur 			break;
593891434b1SRayagond Kokatanur 		}
594891434b1SRayagond Kokatanur 	}
595891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
5965f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
597891434b1SRayagond Kokatanur 
598891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
599891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
600891434b1SRayagond Kokatanur 	else {
601891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
602891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
603891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
604891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
605891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
606891434b1SRayagond Kokatanur 
607891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
60819d857c9SPhil Reid 		sec_inc = priv->hw->ptp->config_sub_second_increment(
60919d857c9SPhil Reid 			priv->ioaddr, priv->clk_ptp_rate);
61019d857c9SPhil Reid 		temp = div_u64(1000000000ULL, sec_inc);
611891434b1SRayagond Kokatanur 
612891434b1SRayagond Kokatanur 		/* calculate default added value:
613891434b1SRayagond Kokatanur 		 * formula is :
614891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
61519d857c9SPhil Reid 		 * where, freq_div_ratio = 1e9ns/sec_inc
616891434b1SRayagond Kokatanur 		 */
61719d857c9SPhil Reid 		temp = (u64)(temp << 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 */
6230a624155SArnd Bergmann 		ktime_get_real_ts64(&now);
6240a624155SArnd Bergmann 
6250a624155SArnd Bergmann 		/* lower 32 bits of tv_sec are safe until y2106 */
6260a624155SArnd Bergmann 		priv->hw->ptp->init_systime(priv->ioaddr, (u32)now.tv_sec,
627891434b1SRayagond Kokatanur 					    now.tv_nsec);
628891434b1SRayagond Kokatanur 	}
629891434b1SRayagond Kokatanur 
630891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
631891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
632891434b1SRayagond Kokatanur }
633891434b1SRayagond Kokatanur 
63432ceabcaSGiuseppe CAVALLARO /**
635732fdf0eSGiuseppe CAVALLARO  * stmmac_init_ptp - init PTP
63632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
637732fdf0eSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or PTPv2.
63832ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
639732fdf0eSGiuseppe CAVALLARO  * This function also registers the ptp driver.
64032ceabcaSGiuseppe CAVALLARO  */
64192ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
642891434b1SRayagond Kokatanur {
64392ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
64492ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
64592ba6888SRayagond Kokatanur 
6465566401fSGiuseppe CAVALLARO 	/* Fall-back to main clock in case of no PTP ref is passed */
6475566401fSGiuseppe CAVALLARO 	priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
6485566401fSGiuseppe CAVALLARO 	if (IS_ERR(priv->clk_ptp_ref)) {
6495566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
6505566401fSGiuseppe CAVALLARO 		priv->clk_ptp_ref = NULL;
6515566401fSGiuseppe CAVALLARO 	} else {
6525566401fSGiuseppe CAVALLARO 		clk_prepare_enable(priv->clk_ptp_ref);
6535566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
6545566401fSGiuseppe CAVALLARO 	}
6555566401fSGiuseppe CAVALLARO 
656891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6577cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
658891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6597cd01399SVince Bridgers 
6607cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6617cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6627cd01399SVince Bridgers 
6637cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6647cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
665891434b1SRayagond Kokatanur 
666891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
667891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
668891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
66992ba6888SRayagond Kokatanur 
67092ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
67192ba6888SRayagond Kokatanur }
67292ba6888SRayagond Kokatanur 
67392ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
67492ba6888SRayagond Kokatanur {
6755566401fSGiuseppe CAVALLARO 	if (priv->clk_ptp_ref)
6765566401fSGiuseppe CAVALLARO 		clk_disable_unprepare(priv->clk_ptp_ref);
67792ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
678891434b1SRayagond Kokatanur }
679891434b1SRayagond Kokatanur 
6807ac6653aSJeff Kirsher /**
681732fdf0eSGiuseppe CAVALLARO  * stmmac_adjust_link - adjusts the link parameters
6827ac6653aSJeff Kirsher  * @dev: net device structure
683732fdf0eSGiuseppe CAVALLARO  * Description: this is the helper called by the physical abstraction layer
684732fdf0eSGiuseppe CAVALLARO  * drivers to communicate the phy link status. According the speed and duplex
685732fdf0eSGiuseppe CAVALLARO  * this driver can invoke registered glue-logic as well.
686732fdf0eSGiuseppe CAVALLARO  * It also invoke the eee initialization because it could happen when switch
687732fdf0eSGiuseppe CAVALLARO  * on different networks (that are eee capable).
6887ac6653aSJeff Kirsher  */
6897ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6907ac6653aSJeff Kirsher {
6917ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6927ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6937ac6653aSJeff Kirsher 	unsigned long flags;
6947ac6653aSJeff Kirsher 	int new_state = 0;
6957ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6967ac6653aSJeff Kirsher 
6977ac6653aSJeff Kirsher 	if (phydev == NULL)
6987ac6653aSJeff Kirsher 		return;
6997ac6653aSJeff Kirsher 
7007ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
701d765955dSGiuseppe CAVALLARO 
7027ac6653aSJeff Kirsher 	if (phydev->link) {
7037ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
7047ac6653aSJeff Kirsher 
7057ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
7067ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
7077ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
7087ac6653aSJeff Kirsher 			new_state = 1;
7097ac6653aSJeff Kirsher 			if (!(phydev->duplex))
7107ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
7117ac6653aSJeff Kirsher 			else
7127ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
7137ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
7147ac6653aSJeff Kirsher 		}
7157ac6653aSJeff Kirsher 		/* Flow Control operation */
7167ac6653aSJeff Kirsher 		if (phydev->pause)
7177ed24bbeSVince Bridgers 			priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
7187ac6653aSJeff Kirsher 						 fc, pause_time);
7197ac6653aSJeff Kirsher 
7207ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7217ac6653aSJeff Kirsher 			new_state = 1;
7227ac6653aSJeff Kirsher 			switch (phydev->speed) {
7237ac6653aSJeff Kirsher 			case 1000:
7247ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
7257ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7267ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7277ac6653aSJeff Kirsher 				break;
7287ac6653aSJeff Kirsher 			case 100:
7297ac6653aSJeff Kirsher 			case 10:
7307ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
7317ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7327ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
7337ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
7347ac6653aSJeff Kirsher 					} else {
7357ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7367ac6653aSJeff Kirsher 					}
7377ac6653aSJeff Kirsher 				} else {
7387ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7397ac6653aSJeff Kirsher 				}
7407ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7417ac6653aSJeff Kirsher 				break;
7427ac6653aSJeff Kirsher 			default:
7437ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
744ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
745ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7467ac6653aSJeff Kirsher 				break;
7477ac6653aSJeff Kirsher 			}
7487ac6653aSJeff Kirsher 
7497ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7507ac6653aSJeff Kirsher 		}
7517ac6653aSJeff Kirsher 
7527ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7537ac6653aSJeff Kirsher 
7547ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7557ac6653aSJeff Kirsher 			new_state = 1;
7567ac6653aSJeff Kirsher 			priv->oldlink = 1;
7577ac6653aSJeff Kirsher 		}
7587ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7597ac6653aSJeff Kirsher 		new_state = 1;
7607ac6653aSJeff Kirsher 		priv->oldlink = 0;
7617ac6653aSJeff Kirsher 		priv->speed = 0;
7627ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7637ac6653aSJeff Kirsher 	}
7647ac6653aSJeff Kirsher 
7657ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7667ac6653aSJeff Kirsher 		phy_print_status(phydev);
7677ac6653aSJeff Kirsher 
7684741cf9cSGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
7694741cf9cSGiuseppe CAVALLARO 
77052f95bbfSGiuseppe CAVALLARO 	if (phydev->is_pseudo_fixed_link)
77152f95bbfSGiuseppe CAVALLARO 		/* Stop PHY layer to call the hook to adjust the link in case
77252f95bbfSGiuseppe CAVALLARO 		 * of a switch is attached to the stmmac driver.
77352f95bbfSGiuseppe CAVALLARO 		 */
77452f95bbfSGiuseppe CAVALLARO 		phydev->irq = PHY_IGNORE_INTERRUPT;
77552f95bbfSGiuseppe CAVALLARO 	else
77652f95bbfSGiuseppe CAVALLARO 		/* At this stage, init the EEE if supported.
77752f95bbfSGiuseppe CAVALLARO 		 * Never called in case of fixed_link.
778f5351ef7SGiuseppe CAVALLARO 		 */
779f5351ef7SGiuseppe CAVALLARO 		priv->eee_enabled = stmmac_eee_init(priv);
7807ac6653aSJeff Kirsher }
7817ac6653aSJeff Kirsher 
78232ceabcaSGiuseppe CAVALLARO /**
783732fdf0eSGiuseppe CAVALLARO  * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
78432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
78532ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
78632ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
78732ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
78832ceabcaSGiuseppe CAVALLARO  */
789e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
790e58bb43fSGiuseppe CAVALLARO {
791e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
792e58bb43fSGiuseppe CAVALLARO 
793e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7940d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7950d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7960d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7970d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
798e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
799e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
8000d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
801e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
802e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
803e58bb43fSGiuseppe CAVALLARO 		}
804e58bb43fSGiuseppe CAVALLARO 	}
805e58bb43fSGiuseppe CAVALLARO }
806e58bb43fSGiuseppe CAVALLARO 
8077ac6653aSJeff Kirsher /**
8087ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
8097ac6653aSJeff Kirsher  * @dev: net device structure
8107ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
8117ac6653aSJeff Kirsher  * to the mac driver.
8127ac6653aSJeff Kirsher  *  Return value:
8137ac6653aSJeff Kirsher  *  0 on success
8147ac6653aSJeff Kirsher  */
8157ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
8167ac6653aSJeff Kirsher {
8177ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
8187ac6653aSJeff Kirsher 	struct phy_device *phydev;
819d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
8207ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
82179ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
8229cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
8237ac6653aSJeff Kirsher 	priv->oldlink = 0;
8247ac6653aSJeff Kirsher 	priv->speed = 0;
8257ac6653aSJeff Kirsher 	priv->oldduplex = -1;
8267ac6653aSJeff Kirsher 
8275790cf3cSMathieu Olivari 	if (priv->plat->phy_node) {
8285790cf3cSMathieu Olivari 		phydev = of_phy_connect(dev, priv->plat->phy_node,
8295790cf3cSMathieu Olivari 					&stmmac_adjust_link, 0, interface);
8305790cf3cSMathieu Olivari 	} else {
831f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
832f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
833f142af2eSSrinivas Kandagatla 
834d765955dSGiuseppe CAVALLARO 		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8357ac6653aSJeff Kirsher 			 priv->plat->phy_addr);
8365790cf3cSMathieu Olivari 		pr_debug("stmmac_init_phy:  trying to attach to %s\n",
8375790cf3cSMathieu Olivari 			 phy_id_fmt);
8387ac6653aSJeff Kirsher 
8395790cf3cSMathieu Olivari 		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
8405790cf3cSMathieu Olivari 				     interface);
8415790cf3cSMathieu Olivari 	}
8427ac6653aSJeff Kirsher 
843dfc50fcaSAlexey Brodkin 	if (IS_ERR_OR_NULL(phydev)) {
8447ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
845dfc50fcaSAlexey Brodkin 		if (!phydev)
846dfc50fcaSAlexey Brodkin 			return -ENODEV;
847dfc50fcaSAlexey Brodkin 
8487ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8497ac6653aSJeff Kirsher 	}
8507ac6653aSJeff Kirsher 
85179ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
852c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8539cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8549cbadf09SSrinivas Kandagatla 		(max_speed < 1000 && max_speed > 0))
855c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
856c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
85779ee1dc3SSrinivas Kandagatla 
8587ac6653aSJeff Kirsher 	/*
8597ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8607ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8617ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8627ac6653aSJeff Kirsher 	 * device as well.
8637ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8647ac6653aSJeff Kirsher 	 */
86527732381SMathieu Olivari 	if (!priv->plat->phy_node && phydev->phy_id == 0) {
8667ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8677ac6653aSJeff Kirsher 		return -ENODEV;
8687ac6653aSJeff Kirsher 	}
8698e99fc5fSGiuseppe Cavallaro 
8707ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8717ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8727ac6653aSJeff Kirsher 
8737ac6653aSJeff Kirsher 	priv->phydev = phydev;
8747ac6653aSJeff Kirsher 
8757ac6653aSJeff Kirsher 	return 0;
8767ac6653aSJeff Kirsher }
8777ac6653aSJeff Kirsher 
8787ac6653aSJeff Kirsher /**
879732fdf0eSGiuseppe CAVALLARO  * stmmac_display_ring - display ring
88032ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8817ac6653aSJeff Kirsher  * @size: size of the ring.
88232ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
883c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8847ac6653aSJeff Kirsher  */
885c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8867ac6653aSJeff Kirsher {
8877ac6653aSJeff Kirsher 	int i;
888c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
889c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
890c24602efSGiuseppe CAVALLARO 
8917ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
892c24602efSGiuseppe CAVALLARO 		u64 x;
893c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
894c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
895c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
896c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
897c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
898c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
899c24602efSGiuseppe CAVALLARO 			ep++;
900c24602efSGiuseppe CAVALLARO 		} else {
901c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
902c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
903c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
904c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
905c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
906c24602efSGiuseppe CAVALLARO 			p++;
907c24602efSGiuseppe CAVALLARO 		}
9087ac6653aSJeff Kirsher 		pr_info("\n");
9097ac6653aSJeff Kirsher 	}
9107ac6653aSJeff Kirsher }
9117ac6653aSJeff Kirsher 
912c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
913c24602efSGiuseppe CAVALLARO {
914c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
915c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
916e3ad57c9SGiuseppe Cavallaro 		stmmac_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1);
917c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
918e3ad57c9SGiuseppe Cavallaro 		stmmac_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1);
919c24602efSGiuseppe CAVALLARO 	} else {
920c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
921e3ad57c9SGiuseppe Cavallaro 		stmmac_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0);
922c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
923e3ad57c9SGiuseppe Cavallaro 		stmmac_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0);
924c24602efSGiuseppe CAVALLARO 	}
925c24602efSGiuseppe CAVALLARO }
926c24602efSGiuseppe CAVALLARO 
927286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
928286a8372SGiuseppe CAVALLARO {
929286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
930286a8372SGiuseppe CAVALLARO 
931286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
932286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
933286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
934286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
935d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
936286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
937286a8372SGiuseppe CAVALLARO 	else
938d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
939286a8372SGiuseppe CAVALLARO 
940286a8372SGiuseppe CAVALLARO 	return ret;
941286a8372SGiuseppe CAVALLARO }
942286a8372SGiuseppe CAVALLARO 
94332ceabcaSGiuseppe CAVALLARO /**
944732fdf0eSGiuseppe CAVALLARO  * stmmac_clear_descriptors - clear descriptors
94532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
94632ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
94732ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
94832ceabcaSGiuseppe CAVALLARO  */
949c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
950c24602efSGiuseppe CAVALLARO {
951c24602efSGiuseppe CAVALLARO 	int i;
952c24602efSGiuseppe CAVALLARO 
953c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
954e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_RX_SIZE; i++)
955c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
956c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
957c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
958e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_RX_SIZE - 1));
959c24602efSGiuseppe CAVALLARO 		else
960c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
961c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
962e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_RX_SIZE - 1));
963e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++)
964c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
965c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
966c24602efSGiuseppe CAVALLARO 						     priv->mode,
967e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
968c24602efSGiuseppe CAVALLARO 		else
969c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
970c24602efSGiuseppe CAVALLARO 						     priv->mode,
971e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
972c24602efSGiuseppe CAVALLARO }
973c24602efSGiuseppe CAVALLARO 
974732fdf0eSGiuseppe CAVALLARO /**
975732fdf0eSGiuseppe CAVALLARO  * stmmac_init_rx_buffers - init the RX descriptor buffer.
976732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
977732fdf0eSGiuseppe CAVALLARO  * @p: descriptor pointer
978732fdf0eSGiuseppe CAVALLARO  * @i: descriptor index
979732fdf0eSGiuseppe CAVALLARO  * @flags: gfp flag.
980732fdf0eSGiuseppe CAVALLARO  * Description: this function is called to allocate a receive buffer, perform
981732fdf0eSGiuseppe CAVALLARO  * the DMA mapping and init the descriptor.
982732fdf0eSGiuseppe CAVALLARO  */
983c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
984777da230SGiuseppe CAVALLARO 				  int i, gfp_t flags)
985c24602efSGiuseppe CAVALLARO {
986c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
987c24602efSGiuseppe CAVALLARO 
9884ec49a37SVineet Gupta 	skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
98956329137SBartlomiej Zolnierkiewicz 	if (!skb) {
990c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
99156329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
992c24602efSGiuseppe CAVALLARO 	}
993c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
994c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
995c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
996c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
99756329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
99856329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
99956329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
100056329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
100156329137SBartlomiej Zolnierkiewicz 	}
1002c24602efSGiuseppe CAVALLARO 
1003c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
1004c24602efSGiuseppe CAVALLARO 
100529896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
1006c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
100729896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
1008c24602efSGiuseppe CAVALLARO 
1009c24602efSGiuseppe CAVALLARO 	return 0;
1010c24602efSGiuseppe CAVALLARO }
1011c24602efSGiuseppe CAVALLARO 
101256329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
101356329137SBartlomiej Zolnierkiewicz {
101456329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
101556329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
101656329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
101756329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
101856329137SBartlomiej Zolnierkiewicz 	}
101956329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
102056329137SBartlomiej Zolnierkiewicz }
102156329137SBartlomiej Zolnierkiewicz 
10227ac6653aSJeff Kirsher /**
10237ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
10247ac6653aSJeff Kirsher  * @dev: net device structure
1025732fdf0eSGiuseppe CAVALLARO  * @flags: gfp flag.
10267ac6653aSJeff Kirsher  * Description: this function initializes the DMA RX/TX descriptors
1027286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
1028286a8372SGiuseppe CAVALLARO  * modes.
10297ac6653aSJeff Kirsher  */
1030777da230SGiuseppe CAVALLARO static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
10317ac6653aSJeff Kirsher {
10327ac6653aSJeff Kirsher 	int i;
10337ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
10344a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
103556329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
10367ac6653aSJeff Kirsher 
103729896a67SGiuseppe CAVALLARO 	if (priv->hw->mode->set_16kib_bfsize)
103829896a67SGiuseppe CAVALLARO 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
1039286a8372SGiuseppe CAVALLARO 
10404a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
1041286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10427ac6653aSJeff Kirsher 
10432618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
10442618abb7SVince Bridgers 
104583d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1046c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1047c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10487ac6653aSJeff Kirsher 
10497ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
105083d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
105183d7af64SGiuseppe CAVALLARO 	}
1052e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_RX_SIZE; i++) {
1053c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1054c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1055c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1056c24602efSGiuseppe CAVALLARO 		else
1057c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10587ac6653aSJeff Kirsher 
1059777da230SGiuseppe CAVALLARO 		ret = stmmac_init_rx_buffers(priv, p, i, flags);
106056329137SBartlomiej Zolnierkiewicz 		if (ret)
106156329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1062286a8372SGiuseppe CAVALLARO 
106383d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
106483d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
106583d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
106683d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10677ac6653aSJeff Kirsher 	}
10687ac6653aSJeff Kirsher 	priv->cur_rx = 0;
1069e3ad57c9SGiuseppe Cavallaro 	priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
10707ac6653aSJeff Kirsher 	buf_sz = bfsize;
10717ac6653aSJeff Kirsher 
1072c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1073c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1074c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
107529896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
1076e3ad57c9SGiuseppe Cavallaro 					     DMA_RX_SIZE, 1);
107729896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1078e3ad57c9SGiuseppe Cavallaro 					     DMA_TX_SIZE, 1);
1079c24602efSGiuseppe CAVALLARO 		} else {
108029896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
1081e3ad57c9SGiuseppe Cavallaro 					     DMA_RX_SIZE, 0);
108229896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1083e3ad57c9SGiuseppe Cavallaro 					     DMA_TX_SIZE, 0);
1084c24602efSGiuseppe CAVALLARO 		}
10857ac6653aSJeff Kirsher 	}
1086286a8372SGiuseppe CAVALLARO 
1087c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1088e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++) {
1089c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1090c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1091c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1092c24602efSGiuseppe CAVALLARO 		else
1093c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1094c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1095362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].buf = 0;
1096362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].map_as_page = false;
1097553e2ab3SGiuseppe Cavallaro 		priv->tx_skbuff_dma[i].len = 0;
10982a6d8e17SGiuseppe Cavallaro 		priv->tx_skbuff_dma[i].last_segment = false;
1099c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
11004a7d666aSGiuseppe CAVALLARO 	}
1101c24602efSGiuseppe CAVALLARO 
11027ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
11037ac6653aSJeff Kirsher 	priv->cur_tx = 0;
110438979574SBeniamino Galvani 	netdev_reset_queue(priv->dev);
11057ac6653aSJeff Kirsher 
1106c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
11077ac6653aSJeff Kirsher 
1108c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1109c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
111056329137SBartlomiej Zolnierkiewicz 
111156329137SBartlomiej Zolnierkiewicz 	return 0;
111256329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
111356329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
111456329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
111556329137SBartlomiej Zolnierkiewicz 	return ret;
11167ac6653aSJeff Kirsher }
11177ac6653aSJeff Kirsher 
11187ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
11197ac6653aSJeff Kirsher {
11207ac6653aSJeff Kirsher 	int i;
11217ac6653aSJeff Kirsher 
1122e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_RX_SIZE; i++)
112356329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
11247ac6653aSJeff Kirsher }
11257ac6653aSJeff Kirsher 
11267ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11277ac6653aSJeff Kirsher {
11287ac6653aSJeff Kirsher 	int i;
11297ac6653aSJeff Kirsher 
1130e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++) {
1131c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
113275e4364fSdamuzi000 
1133c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1134c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1135c24602efSGiuseppe CAVALLARO 		else
1136c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1137c24602efSGiuseppe CAVALLARO 
1138362b37beSGiuseppe CAVALLARO 		if (priv->tx_skbuff_dma[i].buf) {
1139362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[i].map_as_page)
1140362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1141362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[i].buf,
1142553e2ab3SGiuseppe Cavallaro 					       priv->tx_skbuff_dma[i].len,
11437ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1144362b37beSGiuseppe CAVALLARO 			else
1145362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1146362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[i].buf,
1147553e2ab3SGiuseppe Cavallaro 						 priv->tx_skbuff_dma[i].len,
1148362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
114975e4364fSdamuzi000 		}
115075e4364fSdamuzi000 
115175e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11527ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11537ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
1154362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].buf = 0;
1155362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].map_as_page = false;
11567ac6653aSJeff Kirsher 		}
11577ac6653aSJeff Kirsher 	}
11587ac6653aSJeff Kirsher }
11597ac6653aSJeff Kirsher 
1160732fdf0eSGiuseppe CAVALLARO /**
1161732fdf0eSGiuseppe CAVALLARO  * alloc_dma_desc_resources - alloc TX/RX resources.
1162732fdf0eSGiuseppe CAVALLARO  * @priv: private structure
1163732fdf0eSGiuseppe CAVALLARO  * Description: according to which descriptor can be used (extend or basic)
1164732fdf0eSGiuseppe CAVALLARO  * this function allocates the resources for TX and RX paths. In case of
1165732fdf0eSGiuseppe CAVALLARO  * reception, for example, it pre-allocated the RX socket buffer in order to
1166732fdf0eSGiuseppe CAVALLARO  * allow zero-copy mechanism.
1167732fdf0eSGiuseppe CAVALLARO  */
116809f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
116909f8d696SSrinivas Kandagatla {
117009f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
117109f8d696SSrinivas Kandagatla 
1172e3ad57c9SGiuseppe Cavallaro 	priv->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, sizeof(dma_addr_t),
117309f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
117409f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
117509f8d696SSrinivas Kandagatla 		return -ENOMEM;
117609f8d696SSrinivas Kandagatla 
1177e3ad57c9SGiuseppe Cavallaro 	priv->rx_skbuff = kmalloc_array(DMA_RX_SIZE, sizeof(struct sk_buff *),
117809f8d696SSrinivas Kandagatla 					GFP_KERNEL);
117909f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
118009f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
118109f8d696SSrinivas Kandagatla 
1182e3ad57c9SGiuseppe Cavallaro 	priv->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE,
1183362b37beSGiuseppe CAVALLARO 					    sizeof(*priv->tx_skbuff_dma),
118409f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
118509f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
118609f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
118709f8d696SSrinivas Kandagatla 
1188e3ad57c9SGiuseppe Cavallaro 	priv->tx_skbuff = kmalloc_array(DMA_TX_SIZE, sizeof(struct sk_buff *),
118909f8d696SSrinivas Kandagatla 					GFP_KERNEL);
119009f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
119109f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
119209f8d696SSrinivas Kandagatla 
119309f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
1194e3ad57c9SGiuseppe Cavallaro 		priv->dma_erx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE *
119509f8d696SSrinivas Kandagatla 						    sizeof(struct
119609f8d696SSrinivas Kandagatla 							   dma_extended_desc),
119709f8d696SSrinivas Kandagatla 						    &priv->dma_rx_phy,
119809f8d696SSrinivas Kandagatla 						    GFP_KERNEL);
119909f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
120009f8d696SSrinivas Kandagatla 			goto err_dma;
120109f8d696SSrinivas Kandagatla 
1202e3ad57c9SGiuseppe Cavallaro 		priv->dma_etx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE *
120309f8d696SSrinivas Kandagatla 						    sizeof(struct
120409f8d696SSrinivas Kandagatla 							   dma_extended_desc),
120509f8d696SSrinivas Kandagatla 						    &priv->dma_tx_phy,
120609f8d696SSrinivas Kandagatla 						    GFP_KERNEL);
120709f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
1208e3ad57c9SGiuseppe Cavallaro 			dma_free_coherent(priv->device, DMA_RX_SIZE *
120909f8d696SSrinivas Kandagatla 					  sizeof(struct dma_extended_desc),
121009f8d696SSrinivas Kandagatla 					  priv->dma_erx, priv->dma_rx_phy);
121109f8d696SSrinivas Kandagatla 			goto err_dma;
121209f8d696SSrinivas Kandagatla 		}
121309f8d696SSrinivas Kandagatla 	} else {
1214e3ad57c9SGiuseppe Cavallaro 		priv->dma_rx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE *
121509f8d696SSrinivas Kandagatla 						   sizeof(struct dma_desc),
121609f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
121709f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
121809f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
121909f8d696SSrinivas Kandagatla 			goto err_dma;
122009f8d696SSrinivas Kandagatla 
1221e3ad57c9SGiuseppe Cavallaro 		priv->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE *
122209f8d696SSrinivas Kandagatla 						   sizeof(struct dma_desc),
122309f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
122409f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
122509f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
1226e3ad57c9SGiuseppe Cavallaro 			dma_free_coherent(priv->device, DMA_RX_SIZE *
122709f8d696SSrinivas Kandagatla 					  sizeof(struct dma_desc),
122809f8d696SSrinivas Kandagatla 					  priv->dma_rx, priv->dma_rx_phy);
122909f8d696SSrinivas Kandagatla 			goto err_dma;
123009f8d696SSrinivas Kandagatla 		}
123109f8d696SSrinivas Kandagatla 	}
123209f8d696SSrinivas Kandagatla 
123309f8d696SSrinivas Kandagatla 	return 0;
123409f8d696SSrinivas Kandagatla 
123509f8d696SSrinivas Kandagatla err_dma:
123609f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
123709f8d696SSrinivas Kandagatla err_tx_skbuff:
123809f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
123909f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
124009f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
124109f8d696SSrinivas Kandagatla err_rx_skbuff:
124209f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
124309f8d696SSrinivas Kandagatla 	return ret;
124409f8d696SSrinivas Kandagatla }
124509f8d696SSrinivas Kandagatla 
12467ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
12477ac6653aSJeff Kirsher {
12487ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
12497ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
12507ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
12517ac6653aSJeff Kirsher 
1252ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1253c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
12547ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
1255e3ad57c9SGiuseppe Cavallaro 				  DMA_TX_SIZE * sizeof(struct dma_desc),
12567ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
12577ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
1258e3ad57c9SGiuseppe Cavallaro 				  DMA_RX_SIZE * sizeof(struct dma_desc),
12597ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1260c24602efSGiuseppe CAVALLARO 	} else {
1261e3ad57c9SGiuseppe Cavallaro 		dma_free_coherent(priv->device, DMA_TX_SIZE *
1262c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1263c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1264e3ad57c9SGiuseppe Cavallaro 		dma_free_coherent(priv->device, DMA_RX_SIZE *
1265c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1266c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1267c24602efSGiuseppe CAVALLARO 	}
12687ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12697ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1270cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12717ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12727ac6653aSJeff Kirsher }
12737ac6653aSJeff Kirsher 
12747ac6653aSJeff Kirsher /**
12757ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
127632ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
1277732fdf0eSGiuseppe CAVALLARO  *  Description: it is used for configuring the DMA operation mode register in
1278732fdf0eSGiuseppe CAVALLARO  *  order to program the tx/rx DMA thresholds or Store-And-Forward mode.
12797ac6653aSJeff Kirsher  */
12807ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12817ac6653aSJeff Kirsher {
1282f88203a2SVince Bridgers 	int rxfifosz = priv->plat->rx_fifo_size;
1283f88203a2SVince Bridgers 
1284e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1285f88203a2SVince Bridgers 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
1286e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12877ac6653aSJeff Kirsher 		/*
12887ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12897ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12907ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12917ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12927ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12937ac6653aSJeff Kirsher 		 */
1294f88203a2SVince Bridgers 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE,
1295f88203a2SVince Bridgers 					rxfifosz);
1296b2dec116SSonic Zhang 		priv->xstats.threshold = SF_DMA_MODE;
12977ac6653aSJeff Kirsher 	} else
1298f88203a2SVince Bridgers 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE,
1299f88203a2SVince Bridgers 					rxfifosz);
13007ac6653aSJeff Kirsher }
13017ac6653aSJeff Kirsher 
13027ac6653aSJeff Kirsher /**
1303732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_clean - to manage the transmission completion
130432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
1305732fdf0eSGiuseppe CAVALLARO  * Description: it reclaims the transmit resources after transmission completes.
13067ac6653aSJeff Kirsher  */
13079125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
13087ac6653aSJeff Kirsher {
130938979574SBeniamino Galvani 	unsigned int bytes_compl = 0, pkts_compl = 0;
1310e3ad57c9SGiuseppe Cavallaro 	unsigned int entry = priv->dirty_tx;
13117ac6653aSJeff Kirsher 
1312a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1313a9097a96SGiuseppe CAVALLARO 
13149125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
13159125cdd1SGiuseppe CAVALLARO 
1316e3ad57c9SGiuseppe Cavallaro 	while (entry != priv->cur_tx) {
13177ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1318c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1319c363b658SFabrice Gasnier 		int status;
1320c24602efSGiuseppe CAVALLARO 
1321c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1322c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1323c24602efSGiuseppe CAVALLARO 		else
1324c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
13257ac6653aSJeff Kirsher 
1326c363b658SFabrice Gasnier 		status = priv->hw->desc->tx_status(&priv->dev->stats,
13277ac6653aSJeff Kirsher 						      &priv->xstats, p,
13287ac6653aSJeff Kirsher 						      priv->ioaddr);
1329c363b658SFabrice Gasnier 		/* Check if the descriptor is owned by the DMA */
1330c363b658SFabrice Gasnier 		if (unlikely(status & tx_dma_own))
1331c363b658SFabrice Gasnier 			break;
1332c363b658SFabrice Gasnier 
1333c363b658SFabrice Gasnier 		/* Just consider the last segment and ...*/
1334c363b658SFabrice Gasnier 		if (likely(!(status & tx_not_ls))) {
1335c363b658SFabrice Gasnier 			/* ... verify the status error condition */
1336c363b658SFabrice Gasnier 			if (unlikely(status & tx_err)) {
1337c363b658SFabrice Gasnier 				priv->dev->stats.tx_errors++;
1338c363b658SFabrice Gasnier 			} else {
13397ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
13407ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
1341c363b658SFabrice Gasnier 			}
1342891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
13437ac6653aSJeff Kirsher 		}
13447ac6653aSJeff Kirsher 
1345362b37beSGiuseppe CAVALLARO 		if (likely(priv->tx_skbuff_dma[entry].buf)) {
1346362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[entry].map_as_page)
1347362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1348362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[entry].buf,
1349553e2ab3SGiuseppe Cavallaro 					       priv->tx_skbuff_dma[entry].len,
13507ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1351362b37beSGiuseppe CAVALLARO 			else
1352362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1353362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[entry].buf,
1354553e2ab3SGiuseppe Cavallaro 						 priv->tx_skbuff_dma[entry].len,
1355362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
1356362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].buf = 0;
1357362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].map_as_page = false;
1358cf32deecSRayagond Kokatanur 		}
135929896a67SGiuseppe CAVALLARO 		priv->hw->mode->clean_desc3(priv, p);
13602a6d8e17SGiuseppe Cavallaro 		priv->tx_skbuff_dma[entry].last_segment = false;
136196951366SGiuseppe Cavallaro 		priv->tx_skbuff_dma[entry].is_jumbo = false;
13627ac6653aSJeff Kirsher 
13637ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
136438979574SBeniamino Galvani 			pkts_compl++;
136538979574SBeniamino Galvani 			bytes_compl += skb->len;
13667c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
13677ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
13687ac6653aSJeff Kirsher 		}
13697ac6653aSJeff Kirsher 
13704a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
13717ac6653aSJeff Kirsher 
1372e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
13737ac6653aSJeff Kirsher 	}
1374fbc80823SGiuseppe Cavallaro 	priv->dirty_tx = entry;
137538979574SBeniamino Galvani 
137638979574SBeniamino Galvani 	netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
137738979574SBeniamino Galvani 
13787ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
1379e3ad57c9SGiuseppe Cavallaro 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) {
13807ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13817ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
1382e3ad57c9SGiuseppe Cavallaro 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH) {
138383d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
138483d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13857ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13867ac6653aSJeff Kirsher 		}
13877ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13887ac6653aSJeff Kirsher 	}
1389d765955dSGiuseppe CAVALLARO 
1390d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1391d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1392f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1393d765955dSGiuseppe CAVALLARO 	}
1394a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13957ac6653aSJeff Kirsher }
13967ac6653aSJeff Kirsher 
13979125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13987ac6653aSJeff Kirsher {
13997ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
14007ac6653aSJeff Kirsher }
14017ac6653aSJeff Kirsher 
14029125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
14037ac6653aSJeff Kirsher {
14047ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
14057ac6653aSJeff Kirsher }
14067ac6653aSJeff Kirsher 
14077ac6653aSJeff Kirsher /**
1408732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_err - to manage the tx error
140932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
14107ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
1411732fdf0eSGiuseppe CAVALLARO  * in case of transmission errors.
14127ac6653aSJeff Kirsher  */
14137ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
14147ac6653aSJeff Kirsher {
1415c24602efSGiuseppe CAVALLARO 	int i;
14167ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
14177ac6653aSJeff Kirsher 
14187ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
14197ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1420e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++)
1421c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1422c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1423c24602efSGiuseppe CAVALLARO 						     priv->mode,
1424e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
1425c24602efSGiuseppe CAVALLARO 		else
1426c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1427c24602efSGiuseppe CAVALLARO 						     priv->mode,
1428e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
14297ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
14307ac6653aSJeff Kirsher 	priv->cur_tx = 0;
143138979574SBeniamino Galvani 	netdev_reset_queue(priv->dev);
14327ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
14337ac6653aSJeff Kirsher 
14347ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
14357ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
14367ac6653aSJeff Kirsher }
14377ac6653aSJeff Kirsher 
143832ceabcaSGiuseppe CAVALLARO /**
1439732fdf0eSGiuseppe CAVALLARO  * stmmac_dma_interrupt - DMA ISR
144032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
144132ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
1442732fdf0eSGiuseppe CAVALLARO  * It calls the dwmac dma routine and schedule poll method in case of some
1443732fdf0eSGiuseppe CAVALLARO  * work can be done.
144432ceabcaSGiuseppe CAVALLARO  */
14457ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
14467ac6653aSJeff Kirsher {
14477ac6653aSJeff Kirsher 	int status;
1448f88203a2SVince Bridgers 	int rxfifosz = priv->plat->rx_fifo_size;
14497ac6653aSJeff Kirsher 
14507ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
14519125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
14529125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
14539125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
14549125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
14559125cdd1SGiuseppe CAVALLARO 		}
14569125cdd1SGiuseppe CAVALLARO 	}
14579125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
14587ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
1459b2dec116SSonic Zhang 		if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
1460b2dec116SSonic Zhang 		    (tc <= 256)) {
14617ac6653aSJeff Kirsher 			tc += 64;
1462c405abe2SSonic Zhang 			if (priv->plat->force_thresh_dma_mode)
1463f88203a2SVince Bridgers 				priv->hw->dma->dma_mode(priv->ioaddr, tc, tc,
1464f88203a2SVince Bridgers 							rxfifosz);
1465c405abe2SSonic Zhang 			else
1466c405abe2SSonic Zhang 				priv->hw->dma->dma_mode(priv->ioaddr, tc,
1467f88203a2SVince Bridgers 							SF_DMA_MODE, rxfifosz);
14687ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
14697ac6653aSJeff Kirsher 		}
14707ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
14717ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
14727ac6653aSJeff Kirsher }
14737ac6653aSJeff Kirsher 
147432ceabcaSGiuseppe CAVALLARO /**
147532ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
147632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
147732ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
147832ceabcaSGiuseppe CAVALLARO  */
14791c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
14801c901a46SGiuseppe CAVALLARO {
14811c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14821c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14831c901a46SGiuseppe CAVALLARO 
14841c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14854f795b25SGiuseppe CAVALLARO 
14864f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14871c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14881c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14894f795b25SGiuseppe CAVALLARO 	} else
1490aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14911c901a46SGiuseppe CAVALLARO }
14921c901a46SGiuseppe CAVALLARO 
1493732fdf0eSGiuseppe CAVALLARO /**
1494732fdf0eSGiuseppe CAVALLARO  * stmmac_get_synopsys_id - return the SYINID.
1495732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
1496732fdf0eSGiuseppe CAVALLARO  * Description: this simple function is to decode and return the SYINID
1497732fdf0eSGiuseppe CAVALLARO  * starting from the HW core register.
1498732fdf0eSGiuseppe CAVALLARO  */
1499f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1500f0b9d786SGiuseppe CAVALLARO {
1501f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1502f0b9d786SGiuseppe CAVALLARO 
1503ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1504f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1505f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1506f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1507f0b9d786SGiuseppe CAVALLARO 
1508cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1509f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1510f0b9d786SGiuseppe CAVALLARO 
1511f0b9d786SGiuseppe CAVALLARO 		return synid;
1512f0b9d786SGiuseppe CAVALLARO 	}
1513f0b9d786SGiuseppe CAVALLARO 	return 0;
1514f0b9d786SGiuseppe CAVALLARO }
1515e7434821SGiuseppe CAVALLARO 
151619e30c14SGiuseppe CAVALLARO /**
1517732fdf0eSGiuseppe CAVALLARO  * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
151832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
151932ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
1520732fdf0eSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it checks if the extended descriptors are
1521732fdf0eSGiuseppe CAVALLARO  * supported by the HW capability register.
1522ff3dd78cSGiuseppe CAVALLARO  */
152319e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
152419e30c14SGiuseppe CAVALLARO {
152519e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
152619e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1527c24602efSGiuseppe CAVALLARO 
1528c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1529c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1530c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1531c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1532c24602efSGiuseppe CAVALLARO 		} else
1533c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1534c24602efSGiuseppe CAVALLARO 
153519e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
153619e30c14SGiuseppe CAVALLARO 	} else {
153719e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
153819e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
153919e30c14SGiuseppe CAVALLARO 	}
154019e30c14SGiuseppe CAVALLARO }
154119e30c14SGiuseppe CAVALLARO 
154219e30c14SGiuseppe CAVALLARO /**
1543732fdf0eSGiuseppe CAVALLARO  * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
154432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
154519e30c14SGiuseppe CAVALLARO  * Description:
154619e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1547e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
154819e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
154919e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1550e7434821SGiuseppe CAVALLARO  */
1551e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1552e7434821SGiuseppe CAVALLARO {
15535e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
15543c20f72fSGiuseppe CAVALLARO 
15555e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
15565e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1557e7434821SGiuseppe CAVALLARO 
15581db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
15591db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
15601db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
15611db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1562ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
15631db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
15641db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
15651db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
15661db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
15671db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
15681db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
15691db123fbSRayagond Kokatanur 		/* MMC */
15701db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1571e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
15721db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
15731db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1574e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
15751db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
15761db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1577e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
15781db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
15791db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1580e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
15811db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
15821db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
15831db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
15841db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
15851db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
15861db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
15871db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1588e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15891db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15901db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15911db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15921db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1593e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1594ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
159519e30c14SGiuseppe CAVALLARO 	}
1596e7434821SGiuseppe CAVALLARO 
1597e7434821SGiuseppe CAVALLARO 	return hw_cap;
1598e7434821SGiuseppe CAVALLARO }
1599e7434821SGiuseppe CAVALLARO 
160032ceabcaSGiuseppe CAVALLARO /**
1601732fdf0eSGiuseppe CAVALLARO  * stmmac_check_ether_addr - check if the MAC addr is valid
160232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
160332ceabcaSGiuseppe CAVALLARO  * Description:
160432ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
160532ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
160632ceabcaSGiuseppe CAVALLARO  */
1607bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1608bfab27a1SGiuseppe CAVALLARO {
1609bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
16107ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
1611bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1612bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1613f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1614c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1615bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1616bfab27a1SGiuseppe CAVALLARO 	}
1617c88460b7SHans de Goede }
1618bfab27a1SGiuseppe CAVALLARO 
161932ceabcaSGiuseppe CAVALLARO /**
1620732fdf0eSGiuseppe CAVALLARO  * stmmac_init_dma_engine - DMA init.
162132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
162232ceabcaSGiuseppe CAVALLARO  * Description:
162332ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
162432ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
162532ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
162632ceabcaSGiuseppe CAVALLARO  */
16270f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
16280f1f88a8SGiuseppe CAVALLARO {
1629afea0365SGiuseppe Cavallaro 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, aal = 0;
1630b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1631c24602efSGiuseppe CAVALLARO 	int atds = 0;
1632495db273SGiuseppe Cavallaro 	int ret = 0;
16330f1f88a8SGiuseppe CAVALLARO 
16340f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
16350f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
16360f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1637b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
1638afea0365SGiuseppe Cavallaro 		aal = priv->plat->dma_cfg->aal;
16390f1f88a8SGiuseppe CAVALLARO 	}
16400f1f88a8SGiuseppe CAVALLARO 
1641c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1642c24602efSGiuseppe CAVALLARO 		atds = 1;
1643c24602efSGiuseppe CAVALLARO 
1644495db273SGiuseppe Cavallaro 	ret = priv->hw->dma->reset(priv->ioaddr);
1645495db273SGiuseppe Cavallaro 	if (ret) {
1646495db273SGiuseppe Cavallaro 		dev_err(priv->device, "Failed to reset the dma\n");
1647495db273SGiuseppe Cavallaro 		return ret;
1648495db273SGiuseppe Cavallaro 	}
1649495db273SGiuseppe Cavallaro 
1650495db273SGiuseppe Cavallaro 	priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
1651afea0365SGiuseppe Cavallaro 			    aal, priv->dma_tx_phy, priv->dma_rx_phy, atds);
1652afea0365SGiuseppe Cavallaro 
1653afea0365SGiuseppe Cavallaro 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) &&
1654afea0365SGiuseppe Cavallaro 	    (priv->plat->axi && priv->hw->dma->axi))
1655afea0365SGiuseppe Cavallaro 		priv->hw->dma->axi(priv->ioaddr, priv->plat->axi);
1656afea0365SGiuseppe Cavallaro 
1657495db273SGiuseppe Cavallaro 	return ret;
16580f1f88a8SGiuseppe CAVALLARO }
16590f1f88a8SGiuseppe CAVALLARO 
1660bfab27a1SGiuseppe CAVALLARO /**
1661732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_timer - mitigation sw timer for tx.
16629125cdd1SGiuseppe CAVALLARO  * @data: data pointer
16639125cdd1SGiuseppe CAVALLARO  * Description:
16649125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
16659125cdd1SGiuseppe CAVALLARO  */
16669125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
16679125cdd1SGiuseppe CAVALLARO {
16689125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
16699125cdd1SGiuseppe CAVALLARO 
16709125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
16719125cdd1SGiuseppe CAVALLARO }
16729125cdd1SGiuseppe CAVALLARO 
16739125cdd1SGiuseppe CAVALLARO /**
1674732fdf0eSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce - init tx mitigation options.
167532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
16769125cdd1SGiuseppe CAVALLARO  * Description:
16779125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
16789125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
16799125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
16809125cdd1SGiuseppe CAVALLARO  */
16819125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
16829125cdd1SGiuseppe CAVALLARO {
16839125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
16849125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
16859125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
16869125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
16879125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
16889125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
16899125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
16909125cdd1SGiuseppe CAVALLARO }
16919125cdd1SGiuseppe CAVALLARO 
16929125cdd1SGiuseppe CAVALLARO /**
1693732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_setup - setup mac in a usable state.
1694523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1695523f11b5SSrinivas Kandagatla  *  Description:
1696732fdf0eSGiuseppe CAVALLARO  *  this is the main function to setup the HW in a usable state because the
1697732fdf0eSGiuseppe CAVALLARO  *  dma engine is reset, the core registers are configured (e.g. AXI,
1698732fdf0eSGiuseppe CAVALLARO  *  Checksum features, timers). The DMA is ready to start receiving and
1699732fdf0eSGiuseppe CAVALLARO  *  transmitting.
1700523f11b5SSrinivas Kandagatla  *  Return value:
1701523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1702523f11b5SSrinivas Kandagatla  *  file on failure.
1703523f11b5SSrinivas Kandagatla  */
1704fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
1705523f11b5SSrinivas Kandagatla {
1706523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1707523f11b5SSrinivas Kandagatla 	int ret;
1708523f11b5SSrinivas Kandagatla 
1709523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1710523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1711523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1712523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1713523f11b5SSrinivas Kandagatla 		return ret;
1714523f11b5SSrinivas Kandagatla 	}
1715523f11b5SSrinivas Kandagatla 
1716523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
17177ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
1718523f11b5SSrinivas Kandagatla 
1719523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1720523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1721523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1722523f11b5SSrinivas Kandagatla 
1723523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
17247ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
1725523f11b5SSrinivas Kandagatla 
1726978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
1727978aded4SGiuseppe CAVALLARO 	if (!ret) {
1728978aded4SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload disabled\n");
1729978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
1730d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
1731978aded4SGiuseppe CAVALLARO 	}
1732978aded4SGiuseppe CAVALLARO 
1733523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1734523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1735523f11b5SSrinivas Kandagatla 
1736523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1737523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1738523f11b5SSrinivas Kandagatla 
1739523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1740523f11b5SSrinivas Kandagatla 
1741fe131929SHuacai Chen 	if (init_ptp) {
1742523f11b5SSrinivas Kandagatla 		ret = stmmac_init_ptp(priv);
17437509edd6SHans de Goede 		if (ret && ret != -EOPNOTSUPP)
1744523f11b5SSrinivas Kandagatla 			pr_warn("%s: failed PTP initialisation\n", __func__);
1745fe131929SHuacai Chen 	}
1746523f11b5SSrinivas Kandagatla 
174750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
1748523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1749523f11b5SSrinivas Kandagatla 	if (ret < 0)
1750523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1751523f11b5SSrinivas Kandagatla #endif
1752523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1753523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1754523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1755523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1756523f11b5SSrinivas Kandagatla 
1757523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1758523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
17597ed24bbeSVince Bridgers 		priv->hw->mac->dump_regs(priv->hw);
1760523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1761523f11b5SSrinivas Kandagatla 	}
1762523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1763523f11b5SSrinivas Kandagatla 
1764523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1765523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1766523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1767523f11b5SSrinivas Kandagatla 	}
1768523f11b5SSrinivas Kandagatla 
1769523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
17707ed24bbeSVince Bridgers 		priv->hw->mac->ctrl_ane(priv->hw, 0);
1771523f11b5SSrinivas Kandagatla 
1772523f11b5SSrinivas Kandagatla 	return 0;
1773523f11b5SSrinivas Kandagatla }
1774523f11b5SSrinivas Kandagatla 
1775523f11b5SSrinivas Kandagatla /**
17767ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
17777ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
17787ac6653aSJeff Kirsher  *  Description:
17797ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
17807ac6653aSJeff Kirsher  *  Return value:
17817ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
17827ac6653aSJeff Kirsher  *  file on failure.
17837ac6653aSJeff Kirsher  */
17847ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
17857ac6653aSJeff Kirsher {
17867ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17877ac6653aSJeff Kirsher 	int ret;
17887ac6653aSJeff Kirsher 
17894bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
17904bfcbd7aSFrancesco Virlinzi 
17914d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
17924d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
17937ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1794e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1795e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1796e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
179789df20d9SHans de Goede 			return ret;
17987ac6653aSJeff Kirsher 		}
1799e58bb43fSGiuseppe CAVALLARO 	}
18007ac6653aSJeff Kirsher 
1801523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1802523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1803523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1804523f11b5SSrinivas Kandagatla 
18057ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
180622ad3838SGiuseppe Cavallaro 	priv->rx_copybreak = STMMAC_RX_COPYBREAK;
180756329137SBartlomiej Zolnierkiewicz 
18087262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
180909f8d696SSrinivas Kandagatla 	if (ret < 0) {
181009f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
181109f8d696SSrinivas Kandagatla 		goto dma_desc_error;
181209f8d696SSrinivas Kandagatla 	}
181309f8d696SSrinivas Kandagatla 
1814777da230SGiuseppe CAVALLARO 	ret = init_dma_desc_rings(dev, GFP_KERNEL);
1815777da230SGiuseppe CAVALLARO 	if (ret < 0) {
1816777da230SGiuseppe CAVALLARO 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1817777da230SGiuseppe CAVALLARO 		goto init_error;
1818777da230SGiuseppe CAVALLARO 	}
1819777da230SGiuseppe CAVALLARO 
1820fe131929SHuacai Chen 	ret = stmmac_hw_setup(dev, true);
182156329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1822523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1823c9324d18SGiuseppe CAVALLARO 		goto init_error;
18247ac6653aSJeff Kirsher 	}
18257ac6653aSJeff Kirsher 
1826777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
1827777da230SGiuseppe CAVALLARO 
1828523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1829523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
18307ac6653aSJeff Kirsher 
18317ac6653aSJeff Kirsher 	/* Request the IRQ lines */
18327ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
18337ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
18347ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
18357ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
18367ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1837c9324d18SGiuseppe CAVALLARO 		goto init_error;
18387ac6653aSJeff Kirsher 	}
18397ac6653aSJeff Kirsher 
18407a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
18417a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
18427a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
18437a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
18447a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1845ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1846ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1847c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
18487a13f8f5SFrancesco Virlinzi 		}
18497a13f8f5SFrancesco Virlinzi 	}
18507a13f8f5SFrancesco Virlinzi 
1851d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1852d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
1853d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1854d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1855d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1856d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1857d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1858c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1859d765955dSGiuseppe CAVALLARO 		}
1860d765955dSGiuseppe CAVALLARO 	}
1861d765955dSGiuseppe CAVALLARO 
18627ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
18637ac6653aSJeff Kirsher 	netif_start_queue(dev);
18647ac6653aSJeff Kirsher 
18657ac6653aSJeff Kirsher 	return 0;
18667ac6653aSJeff Kirsher 
1867c9324d18SGiuseppe CAVALLARO lpiirq_error:
1868d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1869d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1870c9324d18SGiuseppe CAVALLARO wolirq_error:
18717a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
18727a13f8f5SFrancesco Virlinzi 
1873c9324d18SGiuseppe CAVALLARO init_error:
1874c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
187556329137SBartlomiej Zolnierkiewicz dma_desc_error:
18767ac6653aSJeff Kirsher 	if (priv->phydev)
18777ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18784bfcbd7aSFrancesco Virlinzi 
18797ac6653aSJeff Kirsher 	return ret;
18807ac6653aSJeff Kirsher }
18817ac6653aSJeff Kirsher 
18827ac6653aSJeff Kirsher /**
18837ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
18847ac6653aSJeff Kirsher  *  @dev : device pointer.
18857ac6653aSJeff Kirsher  *  Description:
18867ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
18877ac6653aSJeff Kirsher  */
18887ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
18897ac6653aSJeff Kirsher {
18907ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18917ac6653aSJeff Kirsher 
1892d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1893d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1894d765955dSGiuseppe CAVALLARO 
18957ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
18967ac6653aSJeff Kirsher 	if (priv->phydev) {
18977ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
18987ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18997ac6653aSJeff Kirsher 		priv->phydev = NULL;
19007ac6653aSJeff Kirsher 	}
19017ac6653aSJeff Kirsher 
19027ac6653aSJeff Kirsher 	netif_stop_queue(dev);
19037ac6653aSJeff Kirsher 
19047ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
19057ac6653aSJeff Kirsher 
19069125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
19079125cdd1SGiuseppe CAVALLARO 
19087ac6653aSJeff Kirsher 	/* Free the IRQ lines */
19097ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
19107a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
19117a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1912d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
1913d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
19147ac6653aSJeff Kirsher 
19157ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
19167ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
19177ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
19187ac6653aSJeff Kirsher 
19197ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
19207ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
19217ac6653aSJeff Kirsher 
19227ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1923bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
19247ac6653aSJeff Kirsher 
19257ac6653aSJeff Kirsher 	netif_carrier_off(dev);
19267ac6653aSJeff Kirsher 
192750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
1928466c5ac8SMathieu Olivari 	stmmac_exit_fs(dev);
1929bfab27a1SGiuseppe CAVALLARO #endif
1930bfab27a1SGiuseppe CAVALLARO 
193192ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
193292ba6888SRayagond Kokatanur 
19337ac6653aSJeff Kirsher 	return 0;
19347ac6653aSJeff Kirsher }
19357ac6653aSJeff Kirsher 
19367ac6653aSJeff Kirsher /**
1937732fdf0eSGiuseppe CAVALLARO  *  stmmac_xmit - Tx entry point of the driver
19387ac6653aSJeff Kirsher  *  @skb : the socket buffer
19397ac6653aSJeff Kirsher  *  @dev : device pointer
194032ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
194132ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
194232ceabcaSGiuseppe CAVALLARO  *  and SG feature.
19437ac6653aSJeff Kirsher  */
19447ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
19457ac6653aSJeff Kirsher {
19467ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
19470e80bdc9SGiuseppe Cavallaro 	unsigned int nopaged_len = skb_headlen(skb);
19484a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
19497ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
19500e80bdc9SGiuseppe Cavallaro 	unsigned int entry, first_entry;
19517ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
19520e80bdc9SGiuseppe Cavallaro 	unsigned int enh_desc;
19537ac6653aSJeff Kirsher 
195416ee817eSFabrice Gasnier 	spin_lock(&priv->tx_lock);
195516ee817eSFabrice Gasnier 
19567ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
195716ee817eSFabrice Gasnier 		spin_unlock(&priv->tx_lock);
19587ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
19597ac6653aSJeff Kirsher 			netif_stop_queue(dev);
19607ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1961ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
19627ac6653aSJeff Kirsher 		}
19637ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
19647ac6653aSJeff Kirsher 	}
19657ac6653aSJeff Kirsher 
1966d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1967d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1968d765955dSGiuseppe CAVALLARO 
1969e3ad57c9SGiuseppe Cavallaro 	entry = priv->cur_tx;
19700e80bdc9SGiuseppe Cavallaro 	first_entry = entry;
19717ac6653aSJeff Kirsher 
19727ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
19737ac6653aSJeff Kirsher 
19740e80bdc9SGiuseppe Cavallaro 	if (likely(priv->extend_desc))
1975c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1976c24602efSGiuseppe CAVALLARO 	else
19777ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1978c24602efSGiuseppe CAVALLARO 
19797ac6653aSJeff Kirsher 	first = desc;
19807ac6653aSJeff Kirsher 
19810e80bdc9SGiuseppe Cavallaro 	priv->tx_skbuff[first_entry] = skb;
19820e80bdc9SGiuseppe Cavallaro 
19830e80bdc9SGiuseppe Cavallaro 	enh_desc = priv->plat->enh_desc;
19844a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
198529896a67SGiuseppe CAVALLARO 	if (enh_desc)
198629896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
198729896a67SGiuseppe CAVALLARO 
19880e80bdc9SGiuseppe Cavallaro 	if (unlikely(is_jumbo)) {
198929896a67SGiuseppe CAVALLARO 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
1990362b37beSGiuseppe CAVALLARO 		if (unlikely(entry < 0))
1991362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
199229896a67SGiuseppe CAVALLARO 	}
19937ac6653aSJeff Kirsher 
19947ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
19959e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
19969e903e08SEric Dumazet 		int len = skb_frag_size(frag);
1997be434d50SGiuseppe Cavallaro 		bool last_segment = (i == (nfrags - 1));
19987ac6653aSJeff Kirsher 
1999e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
2000e3ad57c9SGiuseppe Cavallaro 
20010e80bdc9SGiuseppe Cavallaro 		if (likely(priv->extend_desc))
2002c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
2003c24602efSGiuseppe CAVALLARO 		else
20047ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
20057ac6653aSJeff Kirsher 
2006f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
2007f722380dSIan Campbell 					      DMA_TO_DEVICE);
2008362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
2009362b37beSGiuseppe CAVALLARO 			goto dma_map_err; /* should reuse desc w/o issues */
2010362b37beSGiuseppe CAVALLARO 
20110e80bdc9SGiuseppe Cavallaro 		priv->tx_skbuff[entry] = NULL;
2012362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
2013362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].map_as_page = true;
2014553e2ab3SGiuseppe Cavallaro 		priv->tx_skbuff_dma[entry].len = len;
20150e80bdc9SGiuseppe Cavallaro 		priv->tx_skbuff_dma[entry].last_segment = last_segment;
20160e80bdc9SGiuseppe Cavallaro 
20170e80bdc9SGiuseppe Cavallaro 		/* Prepare the descriptor and set the own bit too */
20184a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
2019be434d50SGiuseppe Cavallaro 						priv->mode, 1, last_segment);
20207ac6653aSJeff Kirsher 	}
20217ac6653aSJeff Kirsher 
2022e3ad57c9SGiuseppe Cavallaro 	entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
2023e3ad57c9SGiuseppe Cavallaro 
2024e3ad57c9SGiuseppe Cavallaro 	priv->cur_tx = entry;
20257ac6653aSJeff Kirsher 
20267ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
20270e80bdc9SGiuseppe Cavallaro 		pr_debug("%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
20280e80bdc9SGiuseppe Cavallaro 			 __func__, priv->cur_tx, priv->dirty_tx, first_entry,
20290e80bdc9SGiuseppe Cavallaro 			 entry, first, nfrags);
203083d7af64SGiuseppe CAVALLARO 
2031c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2032e3ad57c9SGiuseppe Cavallaro 			stmmac_display_ring((void *)priv->dma_etx,
2033e3ad57c9SGiuseppe Cavallaro 					    DMA_TX_SIZE, 1);
2034c24602efSGiuseppe CAVALLARO 		else
2035e3ad57c9SGiuseppe Cavallaro 			stmmac_display_ring((void *)priv->dma_tx,
2036e3ad57c9SGiuseppe Cavallaro 					    DMA_TX_SIZE, 0);
2037c24602efSGiuseppe CAVALLARO 
203883d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
20397ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
20407ac6653aSJeff Kirsher 	}
20410e80bdc9SGiuseppe Cavallaro 
20427ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
204383d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
204483d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
20457ac6653aSJeff Kirsher 		netif_stop_queue(dev);
20467ac6653aSJeff Kirsher 	}
20477ac6653aSJeff Kirsher 
20487ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
20497ac6653aSJeff Kirsher 
20500e80bdc9SGiuseppe Cavallaro 	/* According to the coalesce parameter the IC bit for the latest
20510e80bdc9SGiuseppe Cavallaro 	 * segment is reset and the timer re-started to clean the tx status.
20520e80bdc9SGiuseppe Cavallaro 	 * This approach takes care about the fragments: desc is the first
20530e80bdc9SGiuseppe Cavallaro 	 * element in case of no SG.
20540e80bdc9SGiuseppe Cavallaro 	 */
20550e80bdc9SGiuseppe Cavallaro 	priv->tx_count_frames += nfrags + 1;
20560e80bdc9SGiuseppe Cavallaro 	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
20570e80bdc9SGiuseppe Cavallaro 		mod_timer(&priv->txtimer,
20580e80bdc9SGiuseppe Cavallaro 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
20590e80bdc9SGiuseppe Cavallaro 	} else {
20600e80bdc9SGiuseppe Cavallaro 		priv->tx_count_frames = 0;
20610e80bdc9SGiuseppe Cavallaro 		priv->hw->desc->set_tx_ic(desc);
20620e80bdc9SGiuseppe Cavallaro 		priv->xstats.tx_set_ic_bit++;
20630e80bdc9SGiuseppe Cavallaro 	}
20640e80bdc9SGiuseppe Cavallaro 
20650e80bdc9SGiuseppe Cavallaro 	if (!priv->hwts_tx_en)
20660e80bdc9SGiuseppe Cavallaro 		skb_tx_timestamp(skb);
20670e80bdc9SGiuseppe Cavallaro 
20680e80bdc9SGiuseppe Cavallaro 	/* Ready to fill the first descriptor and set the OWN bit w/o any
20690e80bdc9SGiuseppe Cavallaro 	 * problems because all the descriptors are actually ready to be
20700e80bdc9SGiuseppe Cavallaro 	 * passed to the DMA engine.
20710e80bdc9SGiuseppe Cavallaro 	 */
20720e80bdc9SGiuseppe Cavallaro 	if (likely(!is_jumbo)) {
20730e80bdc9SGiuseppe Cavallaro 		bool last_segment = (nfrags == 0);
20740e80bdc9SGiuseppe Cavallaro 
20750e80bdc9SGiuseppe Cavallaro 		first->des2 = dma_map_single(priv->device, skb->data,
20760e80bdc9SGiuseppe Cavallaro 					     nopaged_len, DMA_TO_DEVICE);
20770e80bdc9SGiuseppe Cavallaro 		if (dma_mapping_error(priv->device, first->des2))
20780e80bdc9SGiuseppe Cavallaro 			goto dma_map_err;
20790e80bdc9SGiuseppe Cavallaro 
20800e80bdc9SGiuseppe Cavallaro 		priv->tx_skbuff_dma[first_entry].buf = first->des2;
20810e80bdc9SGiuseppe Cavallaro 		priv->tx_skbuff_dma[first_entry].len = nopaged_len;
20820e80bdc9SGiuseppe Cavallaro 		priv->tx_skbuff_dma[first_entry].last_segment = last_segment;
20830e80bdc9SGiuseppe Cavallaro 
2084891434b1SRayagond Kokatanur 		if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2085891434b1SRayagond Kokatanur 			     priv->hwts_tx_en)) {
2086891434b1SRayagond Kokatanur 			/* declare that device is doing timestamping */
2087891434b1SRayagond Kokatanur 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2088891434b1SRayagond Kokatanur 			priv->hw->desc->enable_tx_timestamp(first);
2089891434b1SRayagond Kokatanur 		}
2090891434b1SRayagond Kokatanur 
20910e80bdc9SGiuseppe Cavallaro 		/* Prepare the first descriptor setting the OWN bit too */
20920e80bdc9SGiuseppe Cavallaro 		priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len,
20930e80bdc9SGiuseppe Cavallaro 						csum_insertion, priv->mode, 1,
20940e80bdc9SGiuseppe Cavallaro 						last_segment);
20950e80bdc9SGiuseppe Cavallaro 
20960e80bdc9SGiuseppe Cavallaro 		/* The own bit must be the latest setting done when prepare the
20970e80bdc9SGiuseppe Cavallaro 		 * descriptor and then barrier is needed to make sure that
20980e80bdc9SGiuseppe Cavallaro 		 * all is coherent before granting the DMA engine.
20990e80bdc9SGiuseppe Cavallaro 		 */
21000e80bdc9SGiuseppe Cavallaro 		smp_wmb();
21010e80bdc9SGiuseppe Cavallaro 	}
21027ac6653aSJeff Kirsher 
210338979574SBeniamino Galvani 	netdev_sent_queue(dev, skb->len);
21047ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
21057ac6653aSJeff Kirsher 
2106a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
2107362b37beSGiuseppe CAVALLARO 	return NETDEV_TX_OK;
2108a9097a96SGiuseppe CAVALLARO 
2109362b37beSGiuseppe CAVALLARO dma_map_err:
2110758a0ab5SFabrice Gasnier 	spin_unlock(&priv->tx_lock);
2111362b37beSGiuseppe CAVALLARO 	dev_err(priv->device, "Tx dma map failed\n");
2112362b37beSGiuseppe CAVALLARO 	dev_kfree_skb(skb);
2113362b37beSGiuseppe CAVALLARO 	priv->dev->stats.tx_dropped++;
21147ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
21157ac6653aSJeff Kirsher }
21167ac6653aSJeff Kirsher 
2117b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
2118b9381985SVince Bridgers {
2119b9381985SVince Bridgers 	struct ethhdr *ehdr;
2120b9381985SVince Bridgers 	u16 vlanid;
2121b9381985SVince Bridgers 
2122b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
2123b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
2124b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
2125b9381985SVince Bridgers 		/* pop the vlan tag */
2126b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
2127b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
2128b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
2129b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
2130b9381985SVince Bridgers 	}
2131b9381985SVince Bridgers }
2132b9381985SVince Bridgers 
2133b9381985SVince Bridgers 
2134120e87f9SGiuseppe Cavallaro static inline int stmmac_rx_threshold_count(struct stmmac_priv *priv)
2135120e87f9SGiuseppe Cavallaro {
2136120e87f9SGiuseppe Cavallaro 	if (priv->rx_zeroc_thresh < STMMAC_RX_THRESH)
2137120e87f9SGiuseppe Cavallaro 		return 0;
2138120e87f9SGiuseppe Cavallaro 
2139120e87f9SGiuseppe Cavallaro 	return 1;
2140120e87f9SGiuseppe Cavallaro }
2141120e87f9SGiuseppe Cavallaro 
214232ceabcaSGiuseppe CAVALLARO /**
2143732fdf0eSGiuseppe CAVALLARO  * stmmac_rx_refill - refill used skb preallocated buffers
214432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
214532ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
214632ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
214732ceabcaSGiuseppe CAVALLARO  */
21487ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
21497ac6653aSJeff Kirsher {
21507ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
2151e3ad57c9SGiuseppe Cavallaro 	unsigned int entry = priv->dirty_rx;
2152e3ad57c9SGiuseppe Cavallaro 	int dirty = stmmac_rx_dirty(priv);
21537ac6653aSJeff Kirsher 
2154e3ad57c9SGiuseppe Cavallaro 	while (dirty-- > 0) {
2155c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2156c24602efSGiuseppe CAVALLARO 
2157c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2158c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2159c24602efSGiuseppe CAVALLARO 		else
2160c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2161c24602efSGiuseppe CAVALLARO 
21627ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
21637ac6653aSJeff Kirsher 			struct sk_buff *skb;
21647ac6653aSJeff Kirsher 
2165acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
2166120e87f9SGiuseppe Cavallaro 			if (unlikely(!skb)) {
2167120e87f9SGiuseppe Cavallaro 				/* so for a while no zero-copy! */
2168120e87f9SGiuseppe Cavallaro 				priv->rx_zeroc_thresh = STMMAC_RX_THRESH;
2169120e87f9SGiuseppe Cavallaro 				if (unlikely(net_ratelimit()))
2170120e87f9SGiuseppe Cavallaro 					dev_err(priv->device,
2171120e87f9SGiuseppe Cavallaro 						"fail to alloc skb entry %d\n",
2172120e87f9SGiuseppe Cavallaro 						entry);
21737ac6653aSJeff Kirsher 				break;
2174120e87f9SGiuseppe Cavallaro 			}
21757ac6653aSJeff Kirsher 
21767ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
21777ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
21787ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
21797ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
2180362b37beSGiuseppe CAVALLARO 			if (dma_mapping_error(priv->device,
2181362b37beSGiuseppe CAVALLARO 					      priv->rx_skbuff_dma[entry])) {
2182362b37beSGiuseppe CAVALLARO 				dev_err(priv->device, "Rx dma map failed\n");
2183362b37beSGiuseppe CAVALLARO 				dev_kfree_skb(skb);
2184362b37beSGiuseppe CAVALLARO 				break;
2185362b37beSGiuseppe CAVALLARO 			}
2186c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2187286a8372SGiuseppe CAVALLARO 
218829896a67SGiuseppe CAVALLARO 			priv->hw->mode->refill_desc3(priv, p);
2189286a8372SGiuseppe CAVALLARO 
2190120e87f9SGiuseppe Cavallaro 			if (priv->rx_zeroc_thresh > 0)
2191120e87f9SGiuseppe Cavallaro 				priv->rx_zeroc_thresh--;
2192120e87f9SGiuseppe Cavallaro 
219383d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
219483d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
21957ac6653aSJeff Kirsher 		}
2196120e87f9SGiuseppe Cavallaro 
21977ac6653aSJeff Kirsher 		wmb();
2198c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
21998e839891SDeepak Sikri 		wmb();
2200e3ad57c9SGiuseppe Cavallaro 
2201e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
22027ac6653aSJeff Kirsher 	}
2203e3ad57c9SGiuseppe Cavallaro 	priv->dirty_rx = entry;
22047ac6653aSJeff Kirsher }
22057ac6653aSJeff Kirsher 
220632ceabcaSGiuseppe CAVALLARO /**
2207732fdf0eSGiuseppe CAVALLARO  * stmmac_rx - manage the receive process
220832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
220932ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
221032ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
221132ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
221232ceabcaSGiuseppe CAVALLARO  */
22137ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
22147ac6653aSJeff Kirsher {
2215e3ad57c9SGiuseppe Cavallaro 	unsigned int entry = priv->cur_rx;
22167ac6653aSJeff Kirsher 	unsigned int next_entry;
22177ac6653aSJeff Kirsher 	unsigned int count = 0;
2218d2afb5bdSGiuseppe CAVALLARO 	int coe = priv->hw->rx_csum;
22197ac6653aSJeff Kirsher 
222083d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
222183d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2222c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2223e3ad57c9SGiuseppe Cavallaro 			stmmac_display_ring((void *)priv->dma_erx,
2224e3ad57c9SGiuseppe Cavallaro 					    DMA_RX_SIZE, 1);
2225c24602efSGiuseppe CAVALLARO 		else
2226e3ad57c9SGiuseppe Cavallaro 			stmmac_display_ring((void *)priv->dma_rx,
2227e3ad57c9SGiuseppe Cavallaro 					    DMA_RX_SIZE, 0);
22287ac6653aSJeff Kirsher 	}
2229c24602efSGiuseppe CAVALLARO 	while (count < limit) {
22307ac6653aSJeff Kirsher 		int status;
22319401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
22327ac6653aSJeff Kirsher 
2233c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2234c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2235c24602efSGiuseppe CAVALLARO 		else
2236c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2237c24602efSGiuseppe CAVALLARO 
2238c1fa3212SFabrice Gasnier 		/* read the status of the incoming frame */
2239c1fa3212SFabrice Gasnier 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2240c1fa3212SFabrice Gasnier 						   &priv->xstats, p);
2241c1fa3212SFabrice Gasnier 		/* check if managed by the DMA otherwise go ahead */
2242c1fa3212SFabrice Gasnier 		if (unlikely(status & dma_own))
22437ac6653aSJeff Kirsher 			break;
22447ac6653aSJeff Kirsher 
22457ac6653aSJeff Kirsher 		count++;
22467ac6653aSJeff Kirsher 
2247e3ad57c9SGiuseppe Cavallaro 		priv->cur_rx = STMMAC_GET_ENTRY(priv->cur_rx, DMA_RX_SIZE);
2248e3ad57c9SGiuseppe Cavallaro 		next_entry = priv->cur_rx;
2249e3ad57c9SGiuseppe Cavallaro 
2250c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
22519401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2252c24602efSGiuseppe CAVALLARO 		else
22539401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
22547ac6653aSJeff Kirsher 
2255c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2256c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2257c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2258c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2259c24602efSGiuseppe CAVALLARO 							   entry);
2260891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
22617ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2262891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2263891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2264891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2265891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2266891434b1SRayagond Kokatanur 				 * device can reuse it.
2267891434b1SRayagond Kokatanur 				 */
2268891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2269891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2270891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2271ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2272ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2273891434b1SRayagond Kokatanur 			}
2274891434b1SRayagond Kokatanur 		} else {
22757ac6653aSJeff Kirsher 			struct sk_buff *skb;
22767ac6653aSJeff Kirsher 			int frame_len;
22777ac6653aSJeff Kirsher 
2278ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2279ceb69499SGiuseppe CAVALLARO 
2280e527c4a7SGiuseppe CAVALLARO 			/*  check if frame_len fits the preallocated memory */
2281e527c4a7SGiuseppe CAVALLARO 			if (frame_len > priv->dma_buf_sz) {
2282e527c4a7SGiuseppe CAVALLARO 				priv->dev->stats.rx_length_errors++;
2283e527c4a7SGiuseppe CAVALLARO 				break;
2284e527c4a7SGiuseppe CAVALLARO 			}
2285e527c4a7SGiuseppe CAVALLARO 
22867ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2287ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2288ceb69499SGiuseppe CAVALLARO 			 */
22897ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
22907ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
22917ac6653aSJeff Kirsher 
229283d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
22937ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
22947ac6653aSJeff Kirsher 					 p, entry, p->des2);
229583d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
229683d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
229783d7af64SGiuseppe CAVALLARO 						 frame_len, status);
229883d7af64SGiuseppe CAVALLARO 			}
229922ad3838SGiuseppe Cavallaro 
2300120e87f9SGiuseppe Cavallaro 			if (unlikely((frame_len < priv->rx_copybreak) ||
2301120e87f9SGiuseppe Cavallaro 				     stmmac_rx_threshold_count(priv))) {
230222ad3838SGiuseppe Cavallaro 				skb = netdev_alloc_skb_ip_align(priv->dev,
230322ad3838SGiuseppe Cavallaro 								frame_len);
230422ad3838SGiuseppe Cavallaro 				if (unlikely(!skb)) {
230522ad3838SGiuseppe Cavallaro 					if (net_ratelimit())
230622ad3838SGiuseppe Cavallaro 						dev_warn(priv->device,
230722ad3838SGiuseppe Cavallaro 							 "packet dropped\n");
230822ad3838SGiuseppe Cavallaro 					priv->dev->stats.rx_dropped++;
230922ad3838SGiuseppe Cavallaro 					break;
231022ad3838SGiuseppe Cavallaro 				}
231122ad3838SGiuseppe Cavallaro 
231222ad3838SGiuseppe Cavallaro 				dma_sync_single_for_cpu(priv->device,
231322ad3838SGiuseppe Cavallaro 							priv->rx_skbuff_dma
231422ad3838SGiuseppe Cavallaro 							[entry], frame_len,
231522ad3838SGiuseppe Cavallaro 							DMA_FROM_DEVICE);
231622ad3838SGiuseppe Cavallaro 				skb_copy_to_linear_data(skb,
231722ad3838SGiuseppe Cavallaro 							priv->
231822ad3838SGiuseppe Cavallaro 							rx_skbuff[entry]->data,
231922ad3838SGiuseppe Cavallaro 							frame_len);
232022ad3838SGiuseppe Cavallaro 
232122ad3838SGiuseppe Cavallaro 				skb_put(skb, frame_len);
232222ad3838SGiuseppe Cavallaro 				dma_sync_single_for_device(priv->device,
232322ad3838SGiuseppe Cavallaro 							   priv->rx_skbuff_dma
232422ad3838SGiuseppe Cavallaro 							   [entry], frame_len,
232522ad3838SGiuseppe Cavallaro 							   DMA_FROM_DEVICE);
232622ad3838SGiuseppe Cavallaro 			} else {
23277ac6653aSJeff Kirsher 				skb = priv->rx_skbuff[entry];
23287ac6653aSJeff Kirsher 				if (unlikely(!skb)) {
232922ad3838SGiuseppe Cavallaro 					pr_err("%s: Inconsistent Rx chain\n",
23307ac6653aSJeff Kirsher 					       priv->dev->name);
23317ac6653aSJeff Kirsher 					priv->dev->stats.rx_dropped++;
23327ac6653aSJeff Kirsher 					break;
23337ac6653aSJeff Kirsher 				}
23347ac6653aSJeff Kirsher 				prefetch(skb->data - NET_IP_ALIGN);
23357ac6653aSJeff Kirsher 				priv->rx_skbuff[entry] = NULL;
2336120e87f9SGiuseppe Cavallaro 				priv->rx_zeroc_thresh++;
23377ac6653aSJeff Kirsher 
23387ac6653aSJeff Kirsher 				skb_put(skb, frame_len);
23397ac6653aSJeff Kirsher 				dma_unmap_single(priv->device,
23407ac6653aSJeff Kirsher 						 priv->rx_skbuff_dma[entry],
234122ad3838SGiuseppe Cavallaro 						 priv->dma_buf_sz,
234222ad3838SGiuseppe Cavallaro 						 DMA_FROM_DEVICE);
234322ad3838SGiuseppe Cavallaro 			}
234422ad3838SGiuseppe Cavallaro 
234522ad3838SGiuseppe Cavallaro 			stmmac_get_rx_hwtstamp(priv, entry, skb);
234683d7af64SGiuseppe CAVALLARO 
23477ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
234883d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
23497ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
23507ac6653aSJeff Kirsher 			}
235183d7af64SGiuseppe CAVALLARO 
2352b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2353b9381985SVince Bridgers 
23547ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
23557ac6653aSJeff Kirsher 
2356ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
23577ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
235862a2ab93SGiuseppe CAVALLARO 			else
23597ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
236062a2ab93SGiuseppe CAVALLARO 
23617ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
23627ac6653aSJeff Kirsher 
23637ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
23647ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
23657ac6653aSJeff Kirsher 		}
23667ac6653aSJeff Kirsher 		entry = next_entry;
23677ac6653aSJeff Kirsher 	}
23687ac6653aSJeff Kirsher 
23697ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
23707ac6653aSJeff Kirsher 
23717ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
23727ac6653aSJeff Kirsher 
23737ac6653aSJeff Kirsher 	return count;
23747ac6653aSJeff Kirsher }
23757ac6653aSJeff Kirsher 
23767ac6653aSJeff Kirsher /**
23777ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
23787ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
23797ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
23807ac6653aSJeff Kirsher  *	      all interfaces.
23817ac6653aSJeff Kirsher  *  Description :
23829125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
23837ac6653aSJeff Kirsher  */
23847ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
23857ac6653aSJeff Kirsher {
23867ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
23877ac6653aSJeff Kirsher 	int work_done = 0;
23887ac6653aSJeff Kirsher 
23899125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
23909125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
23917ac6653aSJeff Kirsher 
23929125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
23937ac6653aSJeff Kirsher 	if (work_done < budget) {
23947ac6653aSJeff Kirsher 		napi_complete(napi);
23959125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
23967ac6653aSJeff Kirsher 	}
23977ac6653aSJeff Kirsher 	return work_done;
23987ac6653aSJeff Kirsher }
23997ac6653aSJeff Kirsher 
24007ac6653aSJeff Kirsher /**
24017ac6653aSJeff Kirsher  *  stmmac_tx_timeout
24027ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
24037ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
24047284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
24057ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
24067ac6653aSJeff Kirsher  *   in order to transmit a new packet.
24077ac6653aSJeff Kirsher  */
24087ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
24097ac6653aSJeff Kirsher {
24107ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24117ac6653aSJeff Kirsher 
24127ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
24137ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
24147ac6653aSJeff Kirsher }
24157ac6653aSJeff Kirsher 
24167ac6653aSJeff Kirsher /**
241701789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
24187ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
24197ac6653aSJeff Kirsher  *  Description:
24207ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
24217ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
24227ac6653aSJeff Kirsher  *  Return value:
24237ac6653aSJeff Kirsher  *  void.
24247ac6653aSJeff Kirsher  */
242501789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
24267ac6653aSJeff Kirsher {
24277ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24287ac6653aSJeff Kirsher 
24293b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
24307ac6653aSJeff Kirsher }
24317ac6653aSJeff Kirsher 
24327ac6653aSJeff Kirsher /**
24337ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
24347ac6653aSJeff Kirsher  *  @dev : device pointer.
24357ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
24367ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
24377ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
24387ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
24397ac6653aSJeff Kirsher  *  Return value:
24407ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
24417ac6653aSJeff Kirsher  *  file on failure.
24427ac6653aSJeff Kirsher  */
24437ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
24447ac6653aSJeff Kirsher {
24457ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24467ac6653aSJeff Kirsher 	int max_mtu;
24477ac6653aSJeff Kirsher 
24487ac6653aSJeff Kirsher 	if (netif_running(dev)) {
24497ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
24507ac6653aSJeff Kirsher 		return -EBUSY;
24517ac6653aSJeff Kirsher 	}
24527ac6653aSJeff Kirsher 
245348febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
24547ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
24557ac6653aSJeff Kirsher 	else
245645db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
24577ac6653aSJeff Kirsher 
24582618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
24592618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
24602618abb7SVince Bridgers 
24617ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
24627ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
24637ac6653aSJeff Kirsher 		return -EINVAL;
24647ac6653aSJeff Kirsher 	}
24657ac6653aSJeff Kirsher 
24667ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
24677ac6653aSJeff Kirsher 	netdev_update_features(dev);
24687ac6653aSJeff Kirsher 
24697ac6653aSJeff Kirsher 	return 0;
24707ac6653aSJeff Kirsher }
24717ac6653aSJeff Kirsher 
2472c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2473c8f44affSMichał Mirosław 					     netdev_features_t features)
24747ac6653aSJeff Kirsher {
24757ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24767ac6653aSJeff Kirsher 
247738912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
24787ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
2479d2afb5bdSGiuseppe CAVALLARO 
24807ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
2481a188222bSTom Herbert 		features &= ~NETIF_F_CSUM_MASK;
24827ac6653aSJeff Kirsher 
24837ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
24847ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
24857ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2486ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2487ceb69499SGiuseppe CAVALLARO 	 */
24887ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
2489a188222bSTom Herbert 		features &= ~NETIF_F_CSUM_MASK;
24907ac6653aSJeff Kirsher 
24917ac6653aSJeff Kirsher 	return features;
24927ac6653aSJeff Kirsher }
24937ac6653aSJeff Kirsher 
2494d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev,
2495d2afb5bdSGiuseppe CAVALLARO 			       netdev_features_t features)
2496d2afb5bdSGiuseppe CAVALLARO {
2497d2afb5bdSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(netdev);
2498d2afb5bdSGiuseppe CAVALLARO 
2499d2afb5bdSGiuseppe CAVALLARO 	/* Keep the COE Type in case of csum is supporting */
2500d2afb5bdSGiuseppe CAVALLARO 	if (features & NETIF_F_RXCSUM)
2501d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
2502d2afb5bdSGiuseppe CAVALLARO 	else
2503d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
2504d2afb5bdSGiuseppe CAVALLARO 	/* No check needed because rx_coe has been set before and it will be
2505d2afb5bdSGiuseppe CAVALLARO 	 * fixed in case of issue.
2506d2afb5bdSGiuseppe CAVALLARO 	 */
2507d2afb5bdSGiuseppe CAVALLARO 	priv->hw->mac->rx_ipc(priv->hw);
2508d2afb5bdSGiuseppe CAVALLARO 
2509d2afb5bdSGiuseppe CAVALLARO 	return 0;
2510d2afb5bdSGiuseppe CAVALLARO }
2511d2afb5bdSGiuseppe CAVALLARO 
251232ceabcaSGiuseppe CAVALLARO /**
251332ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
251432ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
251532ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
251632ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
2517732fdf0eSGiuseppe CAVALLARO  *  It can call:
2518732fdf0eSGiuseppe CAVALLARO  *  o DMA service routine (to manage incoming frame reception and transmission
2519732fdf0eSGiuseppe CAVALLARO  *    status)
2520732fdf0eSGiuseppe CAVALLARO  *  o Core interrupts to manage: remote wake-up, management counter, LPI
252132ceabcaSGiuseppe CAVALLARO  *    interrupts.
252232ceabcaSGiuseppe CAVALLARO  */
25237ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
25247ac6653aSJeff Kirsher {
25257ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
25267ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
25277ac6653aSJeff Kirsher 
252889f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
252989f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
253089f7f2cfSSrinivas Kandagatla 
25317ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
25327ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
25337ac6653aSJeff Kirsher 		return IRQ_NONE;
25347ac6653aSJeff Kirsher 	}
25357ac6653aSJeff Kirsher 
25367ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2537d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
25387ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
25390982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2540d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2541d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
25420982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2543d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
25440982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2545d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2546d765955dSGiuseppe CAVALLARO 		}
2547d765955dSGiuseppe CAVALLARO 	}
2548d765955dSGiuseppe CAVALLARO 
2549d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
25507ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
25517ac6653aSJeff Kirsher 
25527ac6653aSJeff Kirsher 	return IRQ_HANDLED;
25537ac6653aSJeff Kirsher }
25547ac6653aSJeff Kirsher 
25557ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
25567ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2557ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2558ceb69499SGiuseppe CAVALLARO  */
25597ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
25607ac6653aSJeff Kirsher {
25617ac6653aSJeff Kirsher 	disable_irq(dev->irq);
25627ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
25637ac6653aSJeff Kirsher 	enable_irq(dev->irq);
25647ac6653aSJeff Kirsher }
25657ac6653aSJeff Kirsher #endif
25667ac6653aSJeff Kirsher 
25677ac6653aSJeff Kirsher /**
25687ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
25697ac6653aSJeff Kirsher  *  @dev: Device pointer.
25707ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
25717ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
25727ac6653aSJeff Kirsher  *  @cmd: IOCTL command
25737ac6653aSJeff Kirsher  *  Description:
257432ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
25757ac6653aSJeff Kirsher  */
25767ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
25777ac6653aSJeff Kirsher {
25787ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2579891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
25807ac6653aSJeff Kirsher 
25817ac6653aSJeff Kirsher 	if (!netif_running(dev))
25827ac6653aSJeff Kirsher 		return -EINVAL;
25837ac6653aSJeff Kirsher 
2584891434b1SRayagond Kokatanur 	switch (cmd) {
2585891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2586891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2587891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
25887ac6653aSJeff Kirsher 		if (!priv->phydev)
25897ac6653aSJeff Kirsher 			return -EINVAL;
25907ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2591891434b1SRayagond Kokatanur 		break;
2592891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2593891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2594891434b1SRayagond Kokatanur 		break;
2595891434b1SRayagond Kokatanur 	default:
2596891434b1SRayagond Kokatanur 		break;
2597891434b1SRayagond Kokatanur 	}
25987ac6653aSJeff Kirsher 
25997ac6653aSJeff Kirsher 	return ret;
26007ac6653aSJeff Kirsher }
26017ac6653aSJeff Kirsher 
260250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
26037ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
26047ac29055SGiuseppe CAVALLARO 
2605c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2606c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
26077ac29055SGiuseppe CAVALLARO {
26087ac29055SGiuseppe CAVALLARO 	int i;
2609c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2610c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
26117ac29055SGiuseppe CAVALLARO 
2612c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2613c24602efSGiuseppe CAVALLARO 		u64 x;
2614c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2615c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2616c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2617c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2618c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2619c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2620c24602efSGiuseppe CAVALLARO 			ep++;
2621c24602efSGiuseppe CAVALLARO 		} else {
2622c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2623c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2624c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2625c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2626c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2627c24602efSGiuseppe CAVALLARO 			p++;
2628c24602efSGiuseppe CAVALLARO 		}
26297ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
26307ac29055SGiuseppe CAVALLARO 	}
2631c24602efSGiuseppe CAVALLARO }
26327ac29055SGiuseppe CAVALLARO 
2633c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2634c24602efSGiuseppe CAVALLARO {
2635c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2636c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
26377ac29055SGiuseppe CAVALLARO 
2638c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2639c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2640e3ad57c9SGiuseppe Cavallaro 		sysfs_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1, seq);
2641c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2642e3ad57c9SGiuseppe Cavallaro 		sysfs_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1, seq);
2643c24602efSGiuseppe CAVALLARO 	} else {
2644c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2645e3ad57c9SGiuseppe Cavallaro 		sysfs_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0, seq);
2646c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2647e3ad57c9SGiuseppe Cavallaro 		sysfs_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0, seq);
26487ac29055SGiuseppe CAVALLARO 	}
26497ac29055SGiuseppe CAVALLARO 
26507ac29055SGiuseppe CAVALLARO 	return 0;
26517ac29055SGiuseppe CAVALLARO }
26527ac29055SGiuseppe CAVALLARO 
26537ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
26547ac29055SGiuseppe CAVALLARO {
26557ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
26567ac29055SGiuseppe CAVALLARO }
26577ac29055SGiuseppe CAVALLARO 
26587ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
26597ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
26607ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
26617ac29055SGiuseppe CAVALLARO 	.read = seq_read,
26627ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
266374863948SDjalal Harouni 	.release = single_release,
26647ac29055SGiuseppe CAVALLARO };
26657ac29055SGiuseppe CAVALLARO 
2666e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2667e7434821SGiuseppe CAVALLARO {
2668e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2669e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2670e7434821SGiuseppe CAVALLARO 
267119e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2672e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2673e7434821SGiuseppe CAVALLARO 		return 0;
2674e7434821SGiuseppe CAVALLARO 	}
2675e7434821SGiuseppe CAVALLARO 
2676e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2677e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2678e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2679e7434821SGiuseppe CAVALLARO 
2680e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2681e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2682e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2683e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2684e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2685e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2686e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2687e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2688e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2689e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2690e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2691e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2692e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2693e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2694e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2695e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2696e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2697e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2698e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2699e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2700e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2701e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2702e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2703e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2704e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2705e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2706e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2707e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2708e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2709e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2710e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2711e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2712e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2713e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2714e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2715e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2716e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2717e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2718e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2719e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2720e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2721e7434821SGiuseppe CAVALLARO 
2722e7434821SGiuseppe CAVALLARO 	return 0;
2723e7434821SGiuseppe CAVALLARO }
2724e7434821SGiuseppe CAVALLARO 
2725e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2726e7434821SGiuseppe CAVALLARO {
2727e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2728e7434821SGiuseppe CAVALLARO }
2729e7434821SGiuseppe CAVALLARO 
2730e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2731e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2732e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2733e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2734e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
273574863948SDjalal Harouni 	.release = single_release,
2736e7434821SGiuseppe CAVALLARO };
2737e7434821SGiuseppe CAVALLARO 
27387ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
27397ac29055SGiuseppe CAVALLARO {
2740466c5ac8SMathieu Olivari 	struct stmmac_priv *priv = netdev_priv(dev);
27417ac29055SGiuseppe CAVALLARO 
2742466c5ac8SMathieu Olivari 	/* Create per netdev entries */
2743466c5ac8SMathieu Olivari 	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
2744466c5ac8SMathieu Olivari 
2745466c5ac8SMathieu Olivari 	if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
2746466c5ac8SMathieu Olivari 		pr_err("ERROR %s/%s, debugfs create directory failed\n",
2747466c5ac8SMathieu Olivari 		       STMMAC_RESOURCE_NAME, dev->name);
27487ac29055SGiuseppe CAVALLARO 
27497ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
27507ac29055SGiuseppe CAVALLARO 	}
27517ac29055SGiuseppe CAVALLARO 
27527ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
2753466c5ac8SMathieu Olivari 	priv->dbgfs_rings_status =
2754466c5ac8SMathieu Olivari 		debugfs_create_file("descriptors_status", S_IRUGO,
2755466c5ac8SMathieu Olivari 				    priv->dbgfs_dir, dev,
27567ac29055SGiuseppe CAVALLARO 				    &stmmac_rings_status_fops);
27577ac29055SGiuseppe CAVALLARO 
2758466c5ac8SMathieu Olivari 	if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
27597ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
2760466c5ac8SMathieu Olivari 		debugfs_remove_recursive(priv->dbgfs_dir);
27617ac29055SGiuseppe CAVALLARO 
27627ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
27637ac29055SGiuseppe CAVALLARO 	}
27647ac29055SGiuseppe CAVALLARO 
2765e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2766466c5ac8SMathieu Olivari 	priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
2767466c5ac8SMathieu Olivari 					    priv->dbgfs_dir,
2768e7434821SGiuseppe CAVALLARO 					    dev, &stmmac_dma_cap_fops);
2769e7434821SGiuseppe CAVALLARO 
2770466c5ac8SMathieu Olivari 	if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
2771e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2772466c5ac8SMathieu Olivari 		debugfs_remove_recursive(priv->dbgfs_dir);
2773e7434821SGiuseppe CAVALLARO 
2774e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2775e7434821SGiuseppe CAVALLARO 	}
2776e7434821SGiuseppe CAVALLARO 
27777ac29055SGiuseppe CAVALLARO 	return 0;
27787ac29055SGiuseppe CAVALLARO }
27797ac29055SGiuseppe CAVALLARO 
2780466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev)
27817ac29055SGiuseppe CAVALLARO {
2782466c5ac8SMathieu Olivari 	struct stmmac_priv *priv = netdev_priv(dev);
2783466c5ac8SMathieu Olivari 
2784466c5ac8SMathieu Olivari 	debugfs_remove_recursive(priv->dbgfs_dir);
27857ac29055SGiuseppe CAVALLARO }
278650fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
27877ac29055SGiuseppe CAVALLARO 
27887ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
27897ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
27907ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
27917ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
27927ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
27937ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
2794d2afb5bdSGiuseppe CAVALLARO 	.ndo_set_features = stmmac_set_features,
279501789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
27967ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
27977ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
27987ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
27997ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
28007ac6653aSJeff Kirsher #endif
28017ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
28027ac6653aSJeff Kirsher };
28037ac6653aSJeff Kirsher 
28047ac6653aSJeff Kirsher /**
2805cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
280632ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2807732fdf0eSGiuseppe CAVALLARO  *  Description: this function is to configure the MAC device according to
2808732fdf0eSGiuseppe CAVALLARO  *  some platform parameters or the HW capability register. It prepares the
2809732fdf0eSGiuseppe CAVALLARO  *  driver to use either ring or chain modes and to setup either enhanced or
2810732fdf0eSGiuseppe CAVALLARO  *  normal descriptors.
2811cf3f047bSGiuseppe CAVALLARO  */
2812cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2813cf3f047bSGiuseppe CAVALLARO {
2814cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2815cf3f047bSGiuseppe CAVALLARO 
2816cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
281703f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
281803f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
28193b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
28203b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
28213b57de95SVince Bridgers 				      priv->plat->unicast_filter_entries);
282203f2eecdSMarc Kleine-Budde 	} else {
2823cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
282403f2eecdSMarc Kleine-Budde 	}
2825cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2826cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2827cf3f047bSGiuseppe CAVALLARO 
2828cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2829cf3f047bSGiuseppe CAVALLARO 
2830cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2831cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2832cf3f047bSGiuseppe CAVALLARO 
28334a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
28344a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
283529896a67SGiuseppe CAVALLARO 		priv->hw->mode = &chain_mode_ops;
28364a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
28374a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
28384a7d666aSGiuseppe CAVALLARO 	} else {
283929896a67SGiuseppe CAVALLARO 		priv->hw->mode = &ring_mode_ops;
28404a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
28414a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
28424a7d666aSGiuseppe CAVALLARO 	}
28434a7d666aSGiuseppe CAVALLARO 
2844cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2845cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2846cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2847cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2848cf3f047bSGiuseppe CAVALLARO 
2849cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2850cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2851cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2852cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2853cf3f047bSGiuseppe CAVALLARO 		 */
2854cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2855cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
285638912bdbSDeepak SIKRI 
2857dec2165fSSonic Zhang 		/* TXCOE doesn't work in thresh DMA mode */
2858dec2165fSSonic Zhang 		if (priv->plat->force_thresh_dma_mode)
2859dec2165fSSonic Zhang 			priv->plat->tx_coe = 0;
2860dec2165fSSonic Zhang 		else
286138912bdbSDeepak SIKRI 			priv->plat->tx_coe = priv->dma_cap.tx_coe;
286238912bdbSDeepak SIKRI 
286338912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
286438912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
286538912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
286638912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
286738912bdbSDeepak SIKRI 
2868cf3f047bSGiuseppe CAVALLARO 	} else
2869cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2870cf3f047bSGiuseppe CAVALLARO 
287161369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
287261369d02SByungho An 	stmmac_selec_desc_mode(priv);
287361369d02SByungho An 
2874d2afb5bdSGiuseppe CAVALLARO 	if (priv->plat->rx_coe) {
2875d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
287638912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
287738912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2878d2afb5bdSGiuseppe CAVALLARO 	}
2879cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2880cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2881cf3f047bSGiuseppe CAVALLARO 
2882cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2883cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2884cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2885cf3f047bSGiuseppe CAVALLARO 	}
2886cf3f047bSGiuseppe CAVALLARO 
2887c24602efSGiuseppe CAVALLARO 	return 0;
2888cf3f047bSGiuseppe CAVALLARO }
2889cf3f047bSGiuseppe CAVALLARO 
2890cf3f047bSGiuseppe CAVALLARO /**
2891bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2892bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2893ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2894e56788cfSJoachim Eastwood  * @res: stmmac resource pointer
2895bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2896bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
28979afec6efSAndy Shevchenko  * Return:
289815ffac73SJoachim Eastwood  * returns 0 on success, otherwise errno.
28997ac6653aSJeff Kirsher  */
290015ffac73SJoachim Eastwood int stmmac_dvr_probe(struct device *device,
2901cf3f047bSGiuseppe CAVALLARO 		     struct plat_stmmacenet_data *plat_dat,
2902e56788cfSJoachim Eastwood 		     struct stmmac_resources *res)
29037ac6653aSJeff Kirsher {
29047ac6653aSJeff Kirsher 	int ret = 0;
2905bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2906bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
29077ac6653aSJeff Kirsher 
2908bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
290941de8d4cSJoe Perches 	if (!ndev)
291015ffac73SJoachim Eastwood 		return -ENOMEM;
29117ac6653aSJeff Kirsher 
2912bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
29137ac6653aSJeff Kirsher 
2914bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2915bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2916bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2917bfab27a1SGiuseppe CAVALLARO 
2918bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2919cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2920cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2921e56788cfSJoachim Eastwood 	priv->ioaddr = res->addr;
2922e56788cfSJoachim Eastwood 	priv->dev->base_addr = (unsigned long)res->addr;
2923e56788cfSJoachim Eastwood 
2924e56788cfSJoachim Eastwood 	priv->dev->irq = res->irq;
2925e56788cfSJoachim Eastwood 	priv->wol_irq = res->wol_irq;
2926e56788cfSJoachim Eastwood 	priv->lpi_irq = res->lpi_irq;
2927e56788cfSJoachim Eastwood 
2928e56788cfSJoachim Eastwood 	if (res->mac)
2929e56788cfSJoachim Eastwood 		memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
2930bfab27a1SGiuseppe CAVALLARO 
2931a7a62685SJoachim Eastwood 	dev_set_drvdata(device, priv->dev);
2932803f8fc4SJoachim Eastwood 
2933cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2934cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2935cf3f047bSGiuseppe CAVALLARO 
2936cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2937ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2938ceb69499SGiuseppe CAVALLARO 	 */
2939cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2940cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2941cf3f047bSGiuseppe CAVALLARO 
294262866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
294362866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
294462866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
294562866e98SChen-Yu Tsai 			 __func__);
2946c5bb86c3SKweh, Hock Leong 		/* If failed to obtain stmmac_clk and specific clk_csr value
2947c5bb86c3SKweh, Hock Leong 		 * is NOT passed from the platform, probe fail.
2948c5bb86c3SKweh, Hock Leong 		 */
2949c5bb86c3SKweh, Hock Leong 		if (!priv->plat->clk_csr) {
2950c5e4ddbdSChen-Yu Tsai 			ret = PTR_ERR(priv->stmmac_clk);
295162866e98SChen-Yu Tsai 			goto error_clk_get;
2952c5bb86c3SKweh, Hock Leong 		} else {
2953c5bb86c3SKweh, Hock Leong 			priv->stmmac_clk = NULL;
2954c5bb86c3SKweh, Hock Leong 		}
295562866e98SChen-Yu Tsai 	}
295662866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
295762866e98SChen-Yu Tsai 
29585f9755d2SAndrew Bresticker 	priv->pclk = devm_clk_get(priv->device, "pclk");
29595f9755d2SAndrew Bresticker 	if (IS_ERR(priv->pclk)) {
29605f9755d2SAndrew Bresticker 		if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) {
29615f9755d2SAndrew Bresticker 			ret = -EPROBE_DEFER;
29625f9755d2SAndrew Bresticker 			goto error_pclk_get;
29635f9755d2SAndrew Bresticker 		}
29645f9755d2SAndrew Bresticker 		priv->pclk = NULL;
29655f9755d2SAndrew Bresticker 	}
29665f9755d2SAndrew Bresticker 	clk_prepare_enable(priv->pclk);
29675f9755d2SAndrew Bresticker 
2968c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2969c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2970c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2971c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2972c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2973c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2974c5e4ddbdSChen-Yu Tsai 		}
2975c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2976c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2977c5e4ddbdSChen-Yu Tsai 	}
2978c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2979c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2980c5e4ddbdSChen-Yu Tsai 
2981cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2982c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2983c24602efSGiuseppe CAVALLARO 	if (ret)
298462866e98SChen-Yu Tsai 		goto error_hw_init;
2985cf3f047bSGiuseppe CAVALLARO 
2986cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2987cf3f047bSGiuseppe CAVALLARO 
2988cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2989cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2990bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2991bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
29927ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
29937ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2994f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
29957ac6653aSJeff Kirsher #endif
29967ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
29977ac6653aSJeff Kirsher 
29987ac6653aSJeff Kirsher 	if (flow_ctrl)
29997ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
30007ac6653aSJeff Kirsher 
300162a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
300262a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
300362a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
300462a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
300562a2ab93SGiuseppe CAVALLARO 	 */
300662a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
300762a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
300862a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
300962a2ab93SGiuseppe CAVALLARO 	}
301062a2ab93SGiuseppe CAVALLARO 
3011bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
30127ac6653aSJeff Kirsher 
30137ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
3014a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
30157ac6653aSJeff Kirsher 
3016bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
30177ac6653aSJeff Kirsher 	if (ret) {
3018cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
30196a81c26fSViresh Kumar 		goto error_netdev_register;
30207ac6653aSJeff Kirsher 	}
30217ac6653aSJeff Kirsher 
3022cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
3023cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
3024cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
3025cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
3026cd7201f4SGiuseppe CAVALLARO 	 * clock input.
3027cd7201f4SGiuseppe CAVALLARO 	 */
3028cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
3029cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
3030cd7201f4SGiuseppe CAVALLARO 	else
3031cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
3032cd7201f4SGiuseppe CAVALLARO 
3033e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
3034e58bb43fSGiuseppe CAVALLARO 
30354d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
30364d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
30374bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
30384bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
30394bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
30404bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
30414bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
30426a81c26fSViresh Kumar 			goto error_mdio_register;
30434bfcbd7aSFrancesco Virlinzi 		}
3044e58bb43fSGiuseppe CAVALLARO 	}
30454bfcbd7aSFrancesco Virlinzi 
304615ffac73SJoachim Eastwood 	return 0;
30477ac6653aSJeff Kirsher 
30486a81c26fSViresh Kumar error_mdio_register:
30497ac6653aSJeff Kirsher 	unregister_netdev(ndev);
30506a81c26fSViresh Kumar error_netdev_register:
30516a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
305262866e98SChen-Yu Tsai error_hw_init:
30535f9755d2SAndrew Bresticker 	clk_disable_unprepare(priv->pclk);
30545f9755d2SAndrew Bresticker error_pclk_get:
305562866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
305662866e98SChen-Yu Tsai error_clk_get:
30577ac6653aSJeff Kirsher 	free_netdev(ndev);
30587ac6653aSJeff Kirsher 
305915ffac73SJoachim Eastwood 	return ret;
30607ac6653aSJeff Kirsher }
3061b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
30627ac6653aSJeff Kirsher 
30637ac6653aSJeff Kirsher /**
30647ac6653aSJeff Kirsher  * stmmac_dvr_remove
3065bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
30667ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
3067bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
30687ac6653aSJeff Kirsher  */
3069bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
30707ac6653aSJeff Kirsher {
30717ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
30727ac6653aSJeff Kirsher 
30737ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
30747ac6653aSJeff Kirsher 
30757ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
30767ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
30777ac6653aSJeff Kirsher 
3078bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
30797ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
30807ac6653aSJeff Kirsher 	unregister_netdev(ndev);
3081c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
3082c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
30835f9755d2SAndrew Bresticker 	clk_disable_unprepare(priv->pclk);
308462866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
3085e743471fSBryan O'Donoghue 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
3086e743471fSBryan O'Donoghue 	    priv->pcs != STMMAC_PCS_RTBI)
3087e743471fSBryan O'Donoghue 		stmmac_mdio_unregister(ndev);
30887ac6653aSJeff Kirsher 	free_netdev(ndev);
30897ac6653aSJeff Kirsher 
30907ac6653aSJeff Kirsher 	return 0;
30917ac6653aSJeff Kirsher }
3092b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
30937ac6653aSJeff Kirsher 
3094732fdf0eSGiuseppe CAVALLARO /**
3095732fdf0eSGiuseppe CAVALLARO  * stmmac_suspend - suspend callback
3096732fdf0eSGiuseppe CAVALLARO  * @ndev: net device pointer
3097732fdf0eSGiuseppe CAVALLARO  * Description: this is the function to suspend the device and it is called
3098732fdf0eSGiuseppe CAVALLARO  * by the platform driver to stop the network queue, release the resources,
3099732fdf0eSGiuseppe CAVALLARO  * program the PMT register (for WoL), clean and release driver resources.
3100732fdf0eSGiuseppe CAVALLARO  */
3101bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
31027ac6653aSJeff Kirsher {
31037ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3104f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
31057ac6653aSJeff Kirsher 
31067ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
31077ac6653aSJeff Kirsher 		return 0;
31087ac6653aSJeff Kirsher 
3109102463b1SFrancesco Virlinzi 	if (priv->phydev)
3110102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
3111102463b1SFrancesco Virlinzi 
3112f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
31137ac6653aSJeff Kirsher 
31147ac6653aSJeff Kirsher 	netif_device_detach(ndev);
31157ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
31167ac6653aSJeff Kirsher 
31177ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
31187ac6653aSJeff Kirsher 
31197ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
31207ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
31217ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
3122c24602efSGiuseppe CAVALLARO 
31237ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
312489f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
31257ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
312689f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
312789f7f2cfSSrinivas Kandagatla 	} else {
3128bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
3129db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
3130ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
31315f9755d2SAndrew Bresticker 		clk_disable(priv->pclk);
3132777da230SGiuseppe CAVALLARO 		clk_disable(priv->stmmac_clk);
3133ba1377ffSGiuseppe CAVALLARO 	}
3134f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
31352d871aa0SVince Bridgers 
31362d871aa0SVince Bridgers 	priv->oldlink = 0;
31372d871aa0SVince Bridgers 	priv->speed = 0;
31382d871aa0SVince Bridgers 	priv->oldduplex = -1;
31397ac6653aSJeff Kirsher 	return 0;
31407ac6653aSJeff Kirsher }
3141b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend);
31427ac6653aSJeff Kirsher 
3143732fdf0eSGiuseppe CAVALLARO /**
3144732fdf0eSGiuseppe CAVALLARO  * stmmac_resume - resume callback
3145732fdf0eSGiuseppe CAVALLARO  * @ndev: net device pointer
3146732fdf0eSGiuseppe CAVALLARO  * Description: when resume this function is invoked to setup the DMA and CORE
3147732fdf0eSGiuseppe CAVALLARO  * in a usable state.
3148732fdf0eSGiuseppe CAVALLARO  */
3149bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
31507ac6653aSJeff Kirsher {
31517ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3152f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
31537ac6653aSJeff Kirsher 
31547ac6653aSJeff Kirsher 	if (!netif_running(ndev))
31557ac6653aSJeff Kirsher 		return 0;
31567ac6653aSJeff Kirsher 
3157f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
31587ac6653aSJeff Kirsher 
31597ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
31607ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
31617ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
31627ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
3163ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
3164ceb69499SGiuseppe CAVALLARO 	 */
3165623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
31667ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
316789f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
3168623997fbSSrinivas Kandagatla 	} else {
3169db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
3170ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
3171777da230SGiuseppe CAVALLARO 		clk_enable(priv->stmmac_clk);
31725f9755d2SAndrew Bresticker 		clk_enable(priv->pclk);
3173623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
3174623997fbSSrinivas Kandagatla 		if (priv->mii)
3175623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
3176623997fbSSrinivas Kandagatla 	}
31777ac6653aSJeff Kirsher 
31787ac6653aSJeff Kirsher 	netif_device_attach(ndev);
31797ac6653aSJeff Kirsher 
3180ae79a639SGiuseppe CAVALLARO 	priv->cur_rx = 0;
3181ae79a639SGiuseppe CAVALLARO 	priv->dirty_rx = 0;
3182ae79a639SGiuseppe CAVALLARO 	priv->dirty_tx = 0;
3183ae79a639SGiuseppe CAVALLARO 	priv->cur_tx = 0;
3184ae79a639SGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
3185ae79a639SGiuseppe CAVALLARO 
3186fe131929SHuacai Chen 	stmmac_hw_setup(ndev, false);
3187777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
3188ac316c78SGiuseppe CAVALLARO 	stmmac_set_rx_mode(ndev);
31897ac6653aSJeff Kirsher 
31907ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
31917ac6653aSJeff Kirsher 
31927ac6653aSJeff Kirsher 	netif_start_queue(ndev);
31937ac6653aSJeff Kirsher 
3194f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
3195102463b1SFrancesco Virlinzi 
3196102463b1SFrancesco Virlinzi 	if (priv->phydev)
3197102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
3198102463b1SFrancesco Virlinzi 
31997ac6653aSJeff Kirsher 	return 0;
32007ac6653aSJeff Kirsher }
3201b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume);
3202ba27ec66SGiuseppe CAVALLARO 
32037ac6653aSJeff Kirsher #ifndef MODULE
32047ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
32057ac6653aSJeff Kirsher {
32067ac6653aSJeff Kirsher 	char *opt;
32077ac6653aSJeff Kirsher 
32087ac6653aSJeff Kirsher 	if (!str || !*str)
32097ac6653aSJeff Kirsher 		return -EINVAL;
32107ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
32117ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
3212ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
32137ac6653aSJeff Kirsher 				goto err;
32147ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
3215ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
32167ac6653aSJeff Kirsher 				goto err;
32177ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
3218ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
32197ac6653aSJeff Kirsher 				goto err;
32207ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
3221ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
32227ac6653aSJeff Kirsher 				goto err;
32237ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3224ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
32257ac6653aSJeff Kirsher 				goto err;
32267ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3227ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
32287ac6653aSJeff Kirsher 				goto err;
32297ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3230ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
32317ac6653aSJeff Kirsher 				goto err;
3232506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3233d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3234d765955dSGiuseppe CAVALLARO 				goto err;
32354a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
32364a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
32374a7d666aSGiuseppe CAVALLARO 				goto err;
32387ac6653aSJeff Kirsher 		}
32397ac6653aSJeff Kirsher 	}
32407ac6653aSJeff Kirsher 	return 0;
32417ac6653aSJeff Kirsher 
32427ac6653aSJeff Kirsher err:
32437ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
32447ac6653aSJeff Kirsher 	return -EINVAL;
32457ac6653aSJeff Kirsher }
32467ac6653aSJeff Kirsher 
32477ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3248ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
32496fc0d0f2SGiuseppe Cavallaro 
3250466c5ac8SMathieu Olivari static int __init stmmac_init(void)
3251466c5ac8SMathieu Olivari {
3252466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS
3253466c5ac8SMathieu Olivari 	/* Create debugfs main directory if it doesn't exist yet */
3254466c5ac8SMathieu Olivari 	if (!stmmac_fs_dir) {
3255466c5ac8SMathieu Olivari 		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
3256466c5ac8SMathieu Olivari 
3257466c5ac8SMathieu Olivari 		if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
3258466c5ac8SMathieu Olivari 			pr_err("ERROR %s, debugfs create directory failed\n",
3259466c5ac8SMathieu Olivari 			       STMMAC_RESOURCE_NAME);
3260466c5ac8SMathieu Olivari 
3261466c5ac8SMathieu Olivari 			return -ENOMEM;
3262466c5ac8SMathieu Olivari 		}
3263466c5ac8SMathieu Olivari 	}
3264466c5ac8SMathieu Olivari #endif
3265466c5ac8SMathieu Olivari 
3266466c5ac8SMathieu Olivari 	return 0;
3267466c5ac8SMathieu Olivari }
3268466c5ac8SMathieu Olivari 
3269466c5ac8SMathieu Olivari static void __exit stmmac_exit(void)
3270466c5ac8SMathieu Olivari {
3271466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS
3272466c5ac8SMathieu Olivari 	debugfs_remove_recursive(stmmac_fs_dir);
3273466c5ac8SMathieu Olivari #endif
3274466c5ac8SMathieu Olivari }
3275466c5ac8SMathieu Olivari 
3276466c5ac8SMathieu Olivari module_init(stmmac_init)
3277466c5ac8SMathieu Olivari module_exit(stmmac_exit)
3278466c5ac8SMathieu Olivari 
32796fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
32806fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
32816fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3282