diff options
Diffstat (limited to 'drivers/net/ethernet/freescale')
20 files changed, 1708 insertions, 1556 deletions
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 6048dc8604e..270308315d4 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -67,6 +67,7 @@ config FSL_XGMAC_MDIO  	tristate "Freescale XGMAC MDIO"  	depends on FSL_SOC  	select PHYLIB +	select OF_MDIO  	---help---  	  This driver supports the MDIO bus on the Fman 10G Ethernet MACs. diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile index 549ce13b92a..71debd1c18c 100644 --- a/drivers/net/ethernet/freescale/Makefile +++ b/drivers/net/ethernet/freescale/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o  obj-$(CONFIG_GIANFAR) += gianfar_driver.o  obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o  gianfar_driver-objs := gianfar.o \ -		gianfar_ethtool.o \ -		gianfar_sysfs.o +		gianfar_ethtool.o  obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o  ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 0120217a16d..671d080105a 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -221,7 +221,7 @@ struct bufdesc_ex {  #define BD_ENET_TX_RCMASK       ((ushort)0x003c)  #define BD_ENET_TX_UN           ((ushort)0x0002)  #define BD_ENET_TX_CSL          ((ushort)0x0001) -#define BD_ENET_TX_STATS        ((ushort)0x03ff)        /* All status bits */ +#define BD_ENET_TX_STATS        ((ushort)0x0fff)        /* All status bits */  /*enhanced buffer descriptor control/status used by Ethernet transmit*/  #define BD_ENET_TX_INT          0x40000000 @@ -246,8 +246,8 @@ struct bufdesc_ex {  #define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)  #define FEC_ENET_TX_FRSIZE	2048  #define FEC_ENET_TX_FRPPG	(PAGE_SIZE / FEC_ENET_TX_FRSIZE) -#define TX_RING_SIZE		16	/* Must be power of two */ -#define TX_RING_MOD_MASK	15	/*   for this to work */ +#define TX_RING_SIZE		512	/* Must be power of two */ +#define TX_RING_MOD_MASK	511	/*   for this to work */  #define BD_ENET_RX_INT          0x00800000  #define BD_ENET_RX_PTP          ((ushort)0x0400) @@ -296,8 +296,15 @@ struct fec_enet_private {  	/* The ring entries to be free()ed */  	struct bufdesc	*dirty_tx; +	unsigned short bufdesc_size;  	unsigned short tx_ring_size;  	unsigned short rx_ring_size; +	unsigned short tx_stop_threshold; +	unsigned short tx_wake_threshold; + +	/* Software TSO */ +	char *tso_hdrs; +	dma_addr_t tso_hdrs_dma;  	struct	platform_device *pdev; @@ -339,7 +346,8 @@ struct fec_enet_private {  void fec_ptp_init(struct platform_device *pdev);  void fec_ptp_start_cyclecounter(struct net_device *ndev); -int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); +int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); +int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);  /****************************************************************************/  #endif /* FEC_H */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index b2793b91cc5..77037fd377b 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -29,7 +29,6 @@  #include <linux/ioport.h>  #include <linux/slab.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -37,6 +36,7 @@  #include <linux/in.h>  #include <linux/ip.h>  #include <net/ip.h> +#include <net/tso.h>  #include <linux/tcp.h>  #include <linux/udp.h>  #include <linux/icmp.h> @@ -55,6 +55,7 @@  #include <linux/of_net.h>  #include <linux/regulator/consumer.h>  #include <linux/if_vlan.h> +#include <linux/pinctrl/consumer.h>  #include <asm/cacheflush.h> @@ -98,10 +99,6 @@ static void set_multicast_list(struct net_device *ndev);   * detected as not set during a prior frame transmission, then the   * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs   * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in - * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously - * detected as not set during a prior frame transmission, then the - * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs - * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in   * frames not being transmitted until there is a 0-to-1 transition on   * ENET_TDAR[TDAR].   */ @@ -177,10 +174,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");  #endif  #endif /* CONFIG_M5272 */ -#if (((RX_RING_SIZE + TX_RING_SIZE) * 32) > PAGE_SIZE) -#error "FEC: descriptor ring size constants too large" -#endif -  /* Interrupt events/masks. */  #define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */  #define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */ @@ -236,6 +229,15 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");  #define FEC_PAUSE_FLAG_AUTONEG	0x1  #define FEC_PAUSE_FLAG_ENABLE	0x2 +#define TSO_HEADER_SIZE		128 +/* Max number of allowed TCP segments for software TSO */ +#define FEC_MAX_TSO_SEGS	100 +#define FEC_MAX_SKB_DESCS	(FEC_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) + +#define IS_TSO_HEADER(txq, addr) \ +	((addr >= txq->tso_hdrs_dma) && \ +	(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE)) +  static int mii_cnt;  static inline @@ -291,6 +293,22 @@ struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct fec_enet_priva  		return (new_bd < base) ? (new_bd + ring_size) : new_bd;  } +static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp, +				struct fec_enet_private *fep) +{ +	return ((const char *)bdp - (const char *)base) / fep->bufdesc_size; +} + +static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep) +{ +	int entries; + +	entries = ((const char *)fep->dirty_tx - +			(const char *)fep->cur_tx) / fep->bufdesc_size - 1; + +	return entries > 0 ? entries : entries + fep->tx_ring_size; +} +  static void *swap_buffer(void *bufaddr, int len)  {  	int i; @@ -302,6 +320,11 @@ static void *swap_buffer(void *bufaddr, int len)  	return bufaddr;  } +static inline bool is_ipv4_pkt(struct sk_buff *skb) +{ +	return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; +} +  static int  fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)  { @@ -312,128 +335,435 @@ fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)  	if (unlikely(skb_cow_head(skb, 0)))  		return -1; +	if (is_ipv4_pkt(skb)) +		ip_hdr(skb)->check = 0;  	*(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = 0;  	return 0;  } -static netdev_tx_t -fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) +static void +fec_enet_submit_work(struct bufdesc *bdp, struct fec_enet_private *fep) +{ +	const struct platform_device_id *id_entry = +				platform_get_device_id(fep->pdev); +	struct bufdesc *bdp_pre; + +	bdp_pre = fec_enet_get_prevdesc(bdp, fep); +	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && +	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { +		fep->delay_work.trig_tx = true; +		schedule_delayed_work(&(fep->delay_work.delay_work), +					msecs_to_jiffies(1)); +	} +} + +static int +fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev)  {  	struct fec_enet_private *fep = netdev_priv(ndev);  	const struct platform_device_id *id_entry =  				platform_get_device_id(fep->pdev); -	struct bufdesc *bdp, *bdp_pre; -	void *bufaddr; -	unsigned short	status; +	struct bufdesc *bdp = fep->cur_tx; +	struct bufdesc_ex *ebdp; +	int nr_frags = skb_shinfo(skb)->nr_frags; +	int frag, frag_len; +	unsigned short status; +	unsigned int estatus = 0; +	skb_frag_t *this_frag;  	unsigned int index; +	void *bufaddr; +	int i; -	/* Fill in a Tx ring entry */ +	for (frag = 0; frag < nr_frags; frag++) { +		this_frag = &skb_shinfo(skb)->frags[frag]; +		bdp = fec_enet_get_nextdesc(bdp, fep); +		ebdp = (struct bufdesc_ex *)bdp; + +		status = bdp->cbd_sc; +		status &= ~BD_ENET_TX_STATS; +		status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); +		frag_len = skb_shinfo(skb)->frags[frag].size; + +		/* Handle the last BD specially */ +		if (frag == nr_frags - 1) { +			status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); +			if (fep->bufdesc_ex) { +				estatus |= BD_ENET_TX_INT; +				if (unlikely(skb_shinfo(skb)->tx_flags & +					SKBTX_HW_TSTAMP && fep->hwts_tx_en)) +					estatus |= BD_ENET_TX_TS; +			} +		} + +		if (fep->bufdesc_ex) { +			if (skb->ip_summed == CHECKSUM_PARTIAL) +				estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; +			ebdp->cbd_bdu = 0; +			ebdp->cbd_esc = estatus; +		} + +		bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; + +		index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep); +		if (((unsigned long) bufaddr) & FEC_ALIGNMENT || +			id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { +			memcpy(fep->tx_bounce[index], bufaddr, frag_len); +			bufaddr = fep->tx_bounce[index]; + +			if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) +				swap_buffer(bufaddr, frag_len); +		} + +		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, +						frag_len, DMA_TO_DEVICE); +		if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { +			dev_kfree_skb_any(skb); +			if (net_ratelimit()) +				netdev_err(ndev, "Tx DMA memory map failed\n"); +			goto dma_mapping_error; +		} + +		bdp->cbd_datlen = frag_len; +		bdp->cbd_sc = status; +	} + +	fep->cur_tx = bdp; + +	return 0; + +dma_mapping_error:  	bdp = fep->cur_tx; +	for (i = 0; i < frag; i++) { +		bdp = fec_enet_get_nextdesc(bdp, fep); +		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, +				bdp->cbd_datlen, DMA_TO_DEVICE); +	} +	return NETDEV_TX_OK; +} -	status = bdp->cbd_sc; +static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); +	const struct platform_device_id *id_entry = +				platform_get_device_id(fep->pdev); +	int nr_frags = skb_shinfo(skb)->nr_frags; +	struct bufdesc *bdp, *last_bdp; +	void *bufaddr; +	unsigned short status; +	unsigned short buflen; +	unsigned int estatus = 0; +	unsigned int index; +	int entries_free; +	int ret; -	if (status & BD_ENET_TX_READY) { -		/* Ooops.  All transmit buffers are full.  Bail out. -		 * This should not happen, since ndev->tbusy should be set. -		 */ -		netdev_err(ndev, "tx queue full!\n"); -		return NETDEV_TX_BUSY; +	entries_free = fec_enet_get_free_txdesc_num(fep); +	if (entries_free < MAX_SKB_FRAGS + 1) { +		dev_kfree_skb_any(skb); +		if (net_ratelimit()) +			netdev_err(ndev, "NOT enough BD for SG!\n"); +		return NETDEV_TX_OK;  	}  	/* Protocol checksum off-load for TCP and UDP. */  	if (fec_enet_clear_csum(skb, ndev)) { -		kfree_skb(skb); +		dev_kfree_skb_any(skb);  		return NETDEV_TX_OK;  	} -	/* Clear all of the status flags */ +	/* Fill in a Tx ring entry */ +	bdp = fep->cur_tx; +	status = bdp->cbd_sc;  	status &= ~BD_ENET_TX_STATS;  	/* Set buffer length and buffer pointer */  	bufaddr = skb->data; -	bdp->cbd_datlen = skb->len; - -	/* -	 * On some FEC implementations data must be aligned on -	 * 4-byte boundaries. Use bounce buffers to copy data -	 * and get it aligned. Ugh. -	 */ -	if (fep->bufdesc_ex) -		index = (struct bufdesc_ex *)bdp - -			(struct bufdesc_ex *)fep->tx_bd_base; -	else -		index = bdp - fep->tx_bd_base; +	buflen = skb_headlen(skb); -	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { -		memcpy(fep->tx_bounce[index], skb->data, skb->len); +	index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep); +	if (((unsigned long) bufaddr) & FEC_ALIGNMENT || +		id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { +		memcpy(fep->tx_bounce[index], skb->data, buflen);  		bufaddr = fep->tx_bounce[index]; + +		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) +			swap_buffer(bufaddr, buflen);  	} -	/* -	 * Some design made an incorrect assumption on endian mode of -	 * the system that it's running on. As the result, driver has to -	 * swap every frame going to and coming from the controller. +	/* Push the data cache so the CPM does not get stale memory +	 * data.  	 */ -	if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) -		swap_buffer(bufaddr, skb->len); +	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, +					buflen, DMA_TO_DEVICE); +	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { +		dev_kfree_skb_any(skb); +		if (net_ratelimit()) +			netdev_err(ndev, "Tx DMA memory map failed\n"); +		return NETDEV_TX_OK; +	} +	if (nr_frags) { +		ret = fec_enet_txq_submit_frag_skb(skb, ndev); +		if (ret) +			return ret; +	} else { +		status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); +		if (fep->bufdesc_ex) { +			estatus = BD_ENET_TX_INT; +			if (unlikely(skb_shinfo(skb)->tx_flags & +				SKBTX_HW_TSTAMP && fep->hwts_tx_en)) +				estatus |= BD_ENET_TX_TS; +		} +	} + +	if (fep->bufdesc_ex) { + +		struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; + +		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && +			fep->hwts_tx_en)) +			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + +		if (skb->ip_summed == CHECKSUM_PARTIAL) +			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; + +		ebdp->cbd_bdu = 0; +		ebdp->cbd_esc = estatus; +	} + +	last_bdp = fep->cur_tx; +	index = fec_enet_get_bd_index(fep->tx_bd_base, last_bdp, fep);  	/* Save skb pointer */  	fep->tx_skbuff[index] = skb; -	/* Push the data cache so the CPM does not get stale memory -	 * data. -	 */ -	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr, -			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); +	bdp->cbd_datlen = buflen;  	/* Send it on its way.  Tell FEC it's ready, interrupt when done,  	 * it's the last BD of the frame, and to put the CRC on the end.  	 */ -	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR -			| BD_ENET_TX_LAST | BD_ENET_TX_TC); +	status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);  	bdp->cbd_sc = status; -	if (fep->bufdesc_ex) { +	fec_enet_submit_work(bdp, fep); -		struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; +	/* If this was the last BD in the ring, start at the beginning again. */ +	bdp = fec_enet_get_nextdesc(last_bdp, fep); + +	skb_tx_timestamp(skb); + +	fep->cur_tx = bdp; + +	/* Trigger transmission start */ +	writel(0, fep->hwp + FEC_X_DES_ACTIVE); + +	return 0; +} + +static int +fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev, +			struct bufdesc *bdp, int index, char *data, +			int size, bool last_tcp, bool is_last) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); +	const struct platform_device_id *id_entry = +				platform_get_device_id(fep->pdev); +	struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; +	unsigned short status; +	unsigned int estatus = 0; + +	status = bdp->cbd_sc; +	status &= ~BD_ENET_TX_STATS; + +	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); +	bdp->cbd_datlen = size; + +	if (((unsigned long) data) & FEC_ALIGNMENT || +		id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { +		memcpy(fep->tx_bounce[index], data, size); +		data = fep->tx_bounce[index]; + +		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) +			swap_buffer(data, size); +	} + +	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data, +					size, DMA_TO_DEVICE); +	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { +		dev_kfree_skb_any(skb); +		if (net_ratelimit()) +			netdev_err(ndev, "Tx DMA memory map failed\n"); +		return NETDEV_TX_BUSY; +	} + +	if (fep->bufdesc_ex) { +		if (skb->ip_summed == CHECKSUM_PARTIAL) +			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;  		ebdp->cbd_bdu = 0; -		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && -			fep->hwts_tx_en)) { -			ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT); -			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; -		} else { -			ebdp->cbd_esc = BD_ENET_TX_INT; +		ebdp->cbd_esc = estatus; +	} -			/* Enable protocol checksum flags -			 * We do not bother with the IP Checksum bits as they -			 * are done by the kernel -			 */ -			if (skb->ip_summed == CHECKSUM_PARTIAL) -				ebdp->cbd_esc |= BD_ENET_TX_PINS; +	/* Handle the last BD specially */ +	if (last_tcp) +		status |= (BD_ENET_TX_LAST | BD_ENET_TX_TC); +	if (is_last) { +		status |= BD_ENET_TX_INTR; +		if (fep->bufdesc_ex) +			ebdp->cbd_esc |= BD_ENET_TX_INT; +	} + +	bdp->cbd_sc = status; + +	return 0; +} + +static int +fec_enet_txq_put_hdr_tso(struct sk_buff *skb, struct net_device *ndev, +			struct bufdesc *bdp, int index) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); +	const struct platform_device_id *id_entry = +				platform_get_device_id(fep->pdev); +	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); +	struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; +	void *bufaddr; +	unsigned long dmabuf; +	unsigned short status; +	unsigned int estatus = 0; + +	status = bdp->cbd_sc; +	status &= ~BD_ENET_TX_STATS; +	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); + +	bufaddr = fep->tso_hdrs + index * TSO_HEADER_SIZE; +	dmabuf = fep->tso_hdrs_dma + index * TSO_HEADER_SIZE; +	if (((unsigned long) bufaddr) & FEC_ALIGNMENT || +		id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) { +		memcpy(fep->tx_bounce[index], skb->data, hdr_len); +		bufaddr = fep->tx_bounce[index]; + +		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) +			swap_buffer(bufaddr, hdr_len); + +		dmabuf = dma_map_single(&fep->pdev->dev, bufaddr, +					hdr_len, DMA_TO_DEVICE); +		if (dma_mapping_error(&fep->pdev->dev, dmabuf)) { +			dev_kfree_skb_any(skb); +			if (net_ratelimit()) +				netdev_err(ndev, "Tx DMA memory map failed\n"); +			return NETDEV_TX_BUSY;  		}  	} -	bdp_pre = fec_enet_get_prevdesc(bdp, fep); -	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && -	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { -		fep->delay_work.trig_tx = true; -		schedule_delayed_work(&(fep->delay_work.delay_work), -					msecs_to_jiffies(1)); +	bdp->cbd_bufaddr = dmabuf; +	bdp->cbd_datlen = hdr_len; + +	if (fep->bufdesc_ex) { +		if (skb->ip_summed == CHECKSUM_PARTIAL) +			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; +		ebdp->cbd_bdu = 0; +		ebdp->cbd_esc = estatus;  	} -	/* If this was the last BD in the ring, start at the beginning again. */ -	bdp = fec_enet_get_nextdesc(bdp, fep); +	bdp->cbd_sc = status; -	fep->cur_tx = bdp; +	return 0; +} -	if (fep->cur_tx == fep->dirty_tx) -		netif_stop_queue(ndev); +static int fec_enet_txq_submit_tso(struct sk_buff *skb, struct net_device *ndev) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); +	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); +	int total_len, data_left; +	struct bufdesc *bdp = fep->cur_tx; +	struct tso_t tso; +	unsigned int index = 0; +	int ret; + +	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep)) { +		dev_kfree_skb_any(skb); +		if (net_ratelimit()) +			netdev_err(ndev, "NOT enough BD for TSO!\n"); +		return NETDEV_TX_OK; +	} + +	/* Protocol checksum off-load for TCP and UDP. */ +	if (fec_enet_clear_csum(skb, ndev)) { +		dev_kfree_skb_any(skb); +		return NETDEV_TX_OK; +	} + +	/* Initialize the TSO handler, and prepare the first payload */ +	tso_start(skb, &tso); + +	total_len = skb->len - hdr_len; +	while (total_len > 0) { +		char *hdr; + +		index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep); +		data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); +		total_len -= data_left; + +		/* prepare packet headers: MAC + IP + TCP */ +		hdr = fep->tso_hdrs + index * TSO_HEADER_SIZE; +		tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); +		ret = fec_enet_txq_put_hdr_tso(skb, ndev, bdp, index); +		if (ret) +			goto err_release; + +		while (data_left > 0) { +			int size; + +			size = min_t(int, tso.size, data_left); +			bdp = fec_enet_get_nextdesc(bdp, fep); +			index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep); +			ret = fec_enet_txq_put_data_tso(skb, ndev, bdp, index, tso.data, +							size, size == data_left, +							total_len == 0); +			if (ret) +				goto err_release; + +			data_left -= size; +			tso_build_data(skb, &tso, size); +		} + +		bdp = fec_enet_get_nextdesc(bdp, fep); +	} + +	/* Save skb pointer */ +	fep->tx_skbuff[index] = skb; + +	fec_enet_submit_work(bdp, fep); + +	skb_tx_timestamp(skb); +	fep->cur_tx = bdp;  	/* Trigger transmission start */  	writel(0, fep->hwp + FEC_X_DES_ACTIVE); -	skb_tx_timestamp(skb); +	return 0; + +err_release: +	/* TODO: Release all used data descriptors for TSO */ +	return ret; +} + +static netdev_tx_t +fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); +	int entries_free; +	int ret; + +	if (skb_is_gso(skb)) +		ret = fec_enet_txq_submit_tso(skb, ndev); +	else +		ret = fec_enet_txq_submit_skb(skb, ndev); +	if (ret) +		return ret; + +	entries_free = fec_enet_get_free_txdesc_num(fep); +	if (entries_free <= fep->tx_stop_threshold) +		netif_stop_queue(ndev);  	return NETDEV_TX_OK;  } @@ -525,13 +855,6 @@ fec_restart(struct net_device *ndev, int duplex)  	/* Clear any outstanding interrupt. */  	writel(0xffc00000, fep->hwp + FEC_IEVENT); -	/* Setup multicast filter. */ -	set_multicast_list(ndev); -#ifndef CONFIG_M5272 -	writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); -	writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -#endif -  	/* Set maximum receive buffer size. */  	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); @@ -652,6 +975,13 @@ fec_restart(struct net_device *ndev, int duplex)  	writel(rcntl, fep->hwp + FEC_R_CNTRL); +	/* Setup multicast filter. */ +	set_multicast_list(ndev); +#ifndef CONFIG_M5272 +	writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); +	writel(0, fep->hwp + FEC_HASH_TABLE_LOW); +#endif +  	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {  		/* enable ENET endian swap */  		ecntl |= (1 << 8); @@ -753,6 +1083,7 @@ fec_enet_tx(struct net_device *ndev)  	unsigned short status;  	struct	sk_buff	*skb;  	int	index = 0; +	int	entries_free;  	fep = netdev_priv(ndev);  	bdp = fep->dirty_tx; @@ -766,17 +1097,17 @@ fec_enet_tx(struct net_device *ndev)  		if (bdp == fep->cur_tx)  			break; -		if (fep->bufdesc_ex) -			index = (struct bufdesc_ex *)bdp - -				(struct bufdesc_ex *)fep->tx_bd_base; -		else -			index = bdp - fep->tx_bd_base; - -		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, -				FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); -		bdp->cbd_bufaddr = 0; +		index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);  		skb = fep->tx_skbuff[index]; +		if (!IS_TSO_HEADER(fep, bdp->cbd_bufaddr)) +			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, +					bdp->cbd_datlen, DMA_TO_DEVICE); +		bdp->cbd_bufaddr = 0; +		if (!skb) { +			bdp = fec_enet_get_nextdesc(bdp, fep); +			continue; +		}  		/* Check for errors. */  		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | @@ -795,7 +1126,7 @@ fec_enet_tx(struct net_device *ndev)  				ndev->stats.tx_carrier_errors++;  		} else {  			ndev->stats.tx_packets++; -			ndev->stats.tx_bytes += bdp->cbd_datlen; +			ndev->stats.tx_bytes += skb->len;  		}  		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) && @@ -832,15 +1163,15 @@ fec_enet_tx(struct net_device *ndev)  		/* Since we have freed up a buffer, the ring is no longer full  		 */ -		if (fep->dirty_tx != fep->cur_tx) { -			if (netif_queue_stopped(ndev)) +		if (netif_queue_stopped(ndev)) { +			entries_free = fec_enet_get_free_txdesc_num(fep); +			if (entries_free >= fep->tx_wake_threshold)  				netif_wake_queue(ndev);  		}  	}  	return;  } -  /* During a receive, the cur_rx points to the current incoming buffer.   * When we update through the ring, if the next incoming buffer has   * not been given to the system, we just set the empty indicator, @@ -861,6 +1192,7 @@ fec_enet_rx(struct net_device *ndev, int budget)  	struct	bufdesc_ex *ebdp = NULL;  	bool	vlan_packet_rcvd = false;  	u16	vlan_tag; +	int	index = 0;  #ifdef CONFIG_M532x  	flush_cache_all(); @@ -916,10 +1248,11 @@ fec_enet_rx(struct net_device *ndev, int budget)  		ndev->stats.rx_packets++;  		pkt_len = bdp->cbd_datlen;  		ndev->stats.rx_bytes += pkt_len; -		data = (__u8*)__va(bdp->cbd_bufaddr); -		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, -				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE); +		index = fec_enet_get_bd_index(fep->rx_bd_base, bdp, fep); +		data = fep->rx_skbuff[index]->data; +		dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr, +					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);  		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)  			swap_buffer(data, pkt_len); @@ -999,8 +1332,8 @@ fec_enet_rx(struct net_device *ndev, int budget)  			napi_gro_receive(&fep->napi, skb);  		} -		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data, -				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE); +		dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr, +					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);  rx_processing_done:  		/* Clear the status flags for this buffer */  		status &= ~BD_ENET_RX_STATS; @@ -1247,9 +1580,47 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,  	return 0;  } -static int fec_enet_mdio_reset(struct mii_bus *bus) +static int fec_enet_clk_enable(struct net_device *ndev, bool enable)  { +	struct fec_enet_private *fep = netdev_priv(ndev); +	int ret; + +	if (enable) { +		ret = clk_prepare_enable(fep->clk_ahb); +		if (ret) +			return ret; +		ret = clk_prepare_enable(fep->clk_ipg); +		if (ret) +			goto failed_clk_ipg; +		if (fep->clk_enet_out) { +			ret = clk_prepare_enable(fep->clk_enet_out); +			if (ret) +				goto failed_clk_enet_out; +		} +		if (fep->clk_ptp) { +			ret = clk_prepare_enable(fep->clk_ptp); +			if (ret) +				goto failed_clk_ptp; +		} +	} else { +		clk_disable_unprepare(fep->clk_ahb); +		clk_disable_unprepare(fep->clk_ipg); +		if (fep->clk_enet_out) +			clk_disable_unprepare(fep->clk_enet_out); +		if (fep->clk_ptp) +			clk_disable_unprepare(fep->clk_ptp); +	} +  	return 0; +failed_clk_ptp: +	if (fep->clk_enet_out) +		clk_disable_unprepare(fep->clk_enet_out); +failed_clk_enet_out: +		clk_disable_unprepare(fep->clk_ipg); +failed_clk_ipg: +		clk_disable_unprepare(fep->clk_ahb); + +	return ret;  }  static int fec_enet_mii_probe(struct net_device *ndev) @@ -1361,7 +1732,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)  	 * Reference Manual has an error on this, and gets fixed on i.MX6Q  	 * document.  	 */ -	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000); +	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), 5000000);  	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)  		fep->phy_speed--;  	fep->phy_speed <<= 1; @@ -1376,7 +1747,6 @@ static int fec_enet_mii_init(struct platform_device *pdev)  	fep->mii_bus->name = "fec_enet_mii_bus";  	fep->mii_bus->read = fec_enet_mdio_read;  	fep->mii_bus->write = fec_enet_mdio_write; -	fep->mii_bus->reset = fec_enet_mdio_reset;  	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",  		pdev->name, fep->dev_id + 1);  	fep->mii_bus->priv = fep; @@ -1671,8 +2041,12 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)  	if (!phydev)  		return -ENODEV; -	if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex) -		return fec_ptp_ioctl(ndev, rq, cmd); +	if (fep->bufdesc_ex) { +		if (cmd == SIOCSHWTSTAMP) +			return fec_ptp_set(ndev, rq); +		if (cmd == SIOCGHWTSTAMP) +			return fec_ptp_get(ndev, rq); +	}  	return phy_mii_ioctl(phydev, rq, cmd);  } @@ -1719,6 +2093,12 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)  		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,  				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); +		if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { +			fec_enet_free_buffers(ndev); +			if (net_ratelimit()) +				netdev_err(ndev, "Rx DMA memory map failed\n"); +			return -ENOMEM; +		}  		bdp->cbd_sc = BD_ENET_RX_EMPTY;  		if (fep->bufdesc_ex) { @@ -1761,7 +2141,10 @@ fec_enet_open(struct net_device *ndev)  	struct fec_enet_private *fep = netdev_priv(ndev);  	int ret; -	napi_enable(&fep->napi); +	pinctrl_pm_select_default_state(&fep->pdev->dev); +	ret = fec_enet_clk_enable(ndev, true); +	if (ret) +		return ret;  	/* I should reset the ring buffers here, but I don't yet know  	 * a simple way to do that. @@ -1777,6 +2160,8 @@ fec_enet_open(struct net_device *ndev)  		fec_enet_free_buffers(ndev);  		return ret;  	} + +	napi_enable(&fep->napi);  	phy_start(fep->phy_dev);  	netif_start_queue(ndev);  	fep->opened = 1; @@ -1799,6 +2184,8 @@ fec_enet_close(struct net_device *ndev)  		phy_disconnect(fep->phy_dev);  	} +	fec_enet_clk_enable(ndev, false); +	pinctrl_pm_select_sleep_state(&fep->pdev->dev);  	fec_enet_free_buffers(ndev);  	return 0; @@ -1886,10 +2273,11 @@ fec_set_mac_address(struct net_device *ndev, void *p)  	struct fec_enet_private *fep = netdev_priv(ndev);  	struct sockaddr *addr = p; -	if (!is_valid_ether_addr(addr->sa_data)) -		return -EADDRNOTAVAIL; - -	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); +	if (addr) { +		if (!is_valid_ether_addr(addr->sa_data)) +			return -EADDRNOTAVAIL; +		memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); +	}  	writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |  		(ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24), @@ -1975,23 +2363,43 @@ static int fec_enet_init(struct net_device *ndev)  	const struct platform_device_id *id_entry =  				platform_get_device_id(fep->pdev);  	struct bufdesc *cbd_base; +	int bd_size; + +	/* init the tx & rx ring size */ +	fep->tx_ring_size = TX_RING_SIZE; +	fep->rx_ring_size = RX_RING_SIZE; + +	fep->tx_stop_threshold = FEC_MAX_SKB_DESCS; +	fep->tx_wake_threshold = (fep->tx_ring_size - fep->tx_stop_threshold) / 2; + +	if (fep->bufdesc_ex) +		fep->bufdesc_size = sizeof(struct bufdesc_ex); +	else +		fep->bufdesc_size = sizeof(struct bufdesc); +	bd_size = (fep->tx_ring_size + fep->rx_ring_size) * +			fep->bufdesc_size;  	/* Allocate memory for buffer descriptors. */ -	cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, +	cbd_base = dma_alloc_coherent(NULL, bd_size, &fep->bd_dma,  				      GFP_KERNEL);  	if (!cbd_base)  		return -ENOMEM; +	fep->tso_hdrs = dma_alloc_coherent(NULL, fep->tx_ring_size * TSO_HEADER_SIZE, +						&fep->tso_hdrs_dma, GFP_KERNEL); +	if (!fep->tso_hdrs) { +		dma_free_coherent(NULL, bd_size, cbd_base, fep->bd_dma); +		return -ENOMEM; +	} +  	memset(cbd_base, 0, PAGE_SIZE);  	fep->netdev = ndev;  	/* Get the Ethernet address */  	fec_get_mac(ndev); - -	/* init the tx & rx ring size */ -	fep->tx_ring_size = TX_RING_SIZE; -	fep->rx_ring_size = RX_RING_SIZE; +	/* make sure MAC we just acquired is programmed into the hw */ +	fec_set_mac_address(ndev, NULL);  	/* Set receive and transmit descriptor base. */  	fep->rx_bd_base = cbd_base; @@ -2009,21 +2417,21 @@ static int fec_enet_init(struct net_device *ndev)  	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);  	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT); -	if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN) { +	if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN)  		/* enable hw VLAN support */  		ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; -		ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; -	}  	if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) { +		ndev->gso_max_segs = FEC_MAX_TSO_SEGS; +  		/* enable hw accelerator */  		ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM -				| NETIF_F_RXCSUM); -		ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM -				| NETIF_F_RXCSUM); +				| NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO);  		fep->csum_flags |= FLAG_RX_CSUM_ENABLED;  	} +	ndev->hw_features = ndev->features; +  	fec_restart(ndev, 0);  	return 0; @@ -2099,6 +2507,9 @@ fec_probe(struct platform_device *pdev)  		fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;  #endif +	/* Select default pin state */ +	pinctrl_pm_select_default_state(&pdev->dev); +  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	fep->hwp = devm_ioremap_resource(&pdev->dev, r);  	if (IS_ERR(fep->hwp)) { @@ -2149,26 +2560,10 @@ fec_probe(struct platform_device *pdev)  		fep->bufdesc_ex = 0;  	} -	ret = clk_prepare_enable(fep->clk_ahb); +	ret = fec_enet_clk_enable(ndev, true);  	if (ret)  		goto failed_clk; -	ret = clk_prepare_enable(fep->clk_ipg); -	if (ret) -		goto failed_clk_ipg; - -	if (fep->clk_enet_out) { -		ret = clk_prepare_enable(fep->clk_enet_out); -		if (ret) -			goto failed_clk_enet_out; -	} - -	if (fep->clk_ptp) { -		ret = clk_prepare_enable(fep->clk_ptp); -		if (ret) -			goto failed_clk_ptp; -	} -  	fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");  	if (!IS_ERR(fep->reg_phy)) {  		ret = regulator_enable(fep->reg_phy); @@ -2210,6 +2605,8 @@ fec_probe(struct platform_device *pdev)  	/* Carrier starts down, phylib will bring it up */  	netif_carrier_off(ndev); +	fec_enet_clk_enable(ndev, false); +	pinctrl_pm_select_sleep_state(&pdev->dev);  	ret = register_netdev(ndev);  	if (ret) @@ -2229,15 +2626,7 @@ failed_init:  	if (fep->reg_phy)  		regulator_disable(fep->reg_phy);  failed_regulator: -	if (fep->clk_ptp) -		clk_disable_unprepare(fep->clk_ptp); -failed_clk_ptp: -	if (fep->clk_enet_out) -		clk_disable_unprepare(fep->clk_enet_out); -failed_clk_enet_out: -	clk_disable_unprepare(fep->clk_ipg); -failed_clk_ipg: -	clk_disable_unprepare(fep->clk_ahb); +	fec_enet_clk_enable(ndev, false);  failed_clk:  failed_ioremap:  	free_netdev(ndev); @@ -2257,14 +2646,9 @@ fec_drv_remove(struct platform_device *pdev)  	del_timer_sync(&fep->time_keep);  	if (fep->reg_phy)  		regulator_disable(fep->reg_phy); -	if (fep->clk_ptp) -		clk_disable_unprepare(fep->clk_ptp);  	if (fep->ptp_clock)  		ptp_clock_unregister(fep->ptp_clock); -	if (fep->clk_enet_out) -		clk_disable_unprepare(fep->clk_enet_out); -	clk_disable_unprepare(fep->clk_ipg); -	clk_disable_unprepare(fep->clk_ahb); +	fec_enet_clk_enable(ndev, false);  	free_netdev(ndev);  	return 0; @@ -2281,12 +2665,8 @@ fec_suspend(struct device *dev)  		fec_stop(ndev);  		netif_device_detach(ndev);  	} -	if (fep->clk_ptp) -		clk_disable_unprepare(fep->clk_ptp); -	if (fep->clk_enet_out) -		clk_disable_unprepare(fep->clk_enet_out); -	clk_disable_unprepare(fep->clk_ipg); -	clk_disable_unprepare(fep->clk_ahb); +	fec_enet_clk_enable(ndev, false); +	pinctrl_pm_select_sleep_state(&fep->pdev->dev);  	if (fep->reg_phy)  		regulator_disable(fep->reg_phy); @@ -2307,25 +2687,10 @@ fec_resume(struct device *dev)  			return ret;  	} -	ret = clk_prepare_enable(fep->clk_ahb); -	if (ret) -		goto failed_clk_ahb; - -	ret = clk_prepare_enable(fep->clk_ipg); +	pinctrl_pm_select_default_state(&fep->pdev->dev); +	ret = fec_enet_clk_enable(ndev, true);  	if (ret) -		goto failed_clk_ipg; - -	if (fep->clk_enet_out) { -		ret = clk_prepare_enable(fep->clk_enet_out); -		if (ret) -			goto failed_clk_enet_out; -	} - -	if (fep->clk_ptp) { -		ret = clk_prepare_enable(fep->clk_ptp); -		if (ret) -			goto failed_clk_ptp; -	} +		goto failed_clk;  	if (netif_running(ndev)) {  		fec_restart(ndev, fep->full_duplex); @@ -2334,14 +2699,7 @@ fec_resume(struct device *dev)  	return 0; -failed_clk_ptp: -	if (fep->clk_enet_out) -		clk_disable_unprepare(fep->clk_enet_out); -failed_clk_enet_out: -	clk_disable_unprepare(fep->clk_ipg); -failed_clk_ipg: -	clk_disable_unprepare(fep->clk_ahb); -failed_clk_ahb: +failed_clk:  	if (fep->reg_phy)  		regulator_disable(fep->reg_phy);  	return ret; diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 5007e4f9fff..82386b29914 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -28,7 +28,6 @@  #include <linux/slab.h>  #include <linux/interrupt.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -274,7 +273,7 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,   * @ifreq: ioctl data   * @cmd: particular ioctl requested   */ -int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)  {  	struct fec_enet_private *fep = netdev_priv(ndev); @@ -321,6 +320,20 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)  	    -EFAULT : 0;  } +int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); +	struct hwtstamp_config config; + +	config.flags = 0; +	config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; +	config.rx_filter = (fep->hwts_rx_en ? +			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); + +	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? +		-EFAULT : 0; +} +  /**   * fec_time_keep - call timecounter_read every second to avoid timer overrun   *                 because ENET just support 32bit counter, will timeout in 4s @@ -359,6 +372,7 @@ void fec_ptp_init(struct platform_device *pdev)  	fep->ptp_caps.n_alarm = 0;  	fep->ptp_caps.n_ext_ts = 0;  	fep->ptp_caps.n_per_out = 0; +	fep->ptp_caps.n_pins = 0;  	fep->ptp_caps.pps = 0;  	fep->ptp_caps.adjfreq = fec_ptp_adjfreq;  	fep->ptp_caps.adjtime = fec_ptp_adjtime; diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 6b60582ce8c..cfaf17b70f3 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -24,7 +24,6 @@  #include <linux/ioport.h>  #include <linux/slab.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -92,6 +91,9 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)  	u16 pkt_len, sc;  	int curidx; +	if (budget <= 0) +		return received; +  	/*  	 * First, grab all of the stats for the incoming packet.  	 * These get messed up if we get called due to a busy condition. @@ -790,10 +792,6 @@ static int fs_init_phy(struct net_device *dev)  	phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,  				iface);  	if (!phydev) { -		phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link, -						   iface); -	} -	if (!phydev) {  		dev_err(&dev->dev, "Could not attach to PHY\n");  		return -ENODEV;  	} @@ -1027,9 +1025,16 @@ static int fs_enet_probe(struct platform_device *ofdev)  	fpi->use_napi = 1;  	fpi->napi_weight = 17;  	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); -	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link", -						  NULL))) -		goto out_free_fpi; +	if (!fpi->phy_node && of_phy_is_fixed_link(ofdev->dev.of_node)) { +		err = of_phy_register_fixed_link(ofdev->dev.of_node); +		if (err) +			goto out_free_fpi; + +		/* In the case of a fixed PHY, the DT node associated +		 * to the PHY is the Ethernet MAC DT node. +		 */ +		fpi->phy_node = ofdev->dev.of_node; +	}  	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {  		phy_connection_type = of_get_property(ofdev->dev.of_node, @@ -1083,7 +1088,7 @@ static int fs_enet_probe(struct platform_device *ofdev)  	mac_addr = of_get_mac_address(ofdev->dev.of_node);  	if (mac_addr) -		memcpy(ndev->dev_addr, mac_addr, 6); +		memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);  	ret = fep->ops->allocate_bd(ndev);  	if (ret) diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c index 7583a9572bc..f5383abbf39 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c @@ -20,7 +20,6 @@  #include <linux/errno.h>  #include <linux/ioport.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -32,7 +31,9 @@  #include <linux/fs.h>  #include <linux/platform_device.h>  #include <linux/phy.h> +#include <linux/of_address.h>  #include <linux/of_device.h> +#include <linux/of_irq.h>  #include <linux/gfp.h>  #include <asm/immap_cpm2.h> @@ -88,7 +89,7 @@ static int do_pd_setup(struct fs_enet_private *fep)  	struct fs_platform_info *fpi = fep->fpi;  	int ret = -EINVAL; -	fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); +	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);  	if (fep->interrupt == NO_IRQ)  		goto out; diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c index 9ae6cdbcac2..fc541348849 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c @@ -20,7 +20,6 @@  #include <linux/errno.h>  #include <linux/ioport.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -31,7 +30,9 @@  #include <linux/bitops.h>  #include <linux/fs.h>  #include <linux/platform_device.h> +#include <linux/of_address.h>  #include <linux/of_device.h> +#include <linux/of_irq.h>  #include <linux/gfp.h>  #include <asm/irq.h> @@ -98,7 +99,7 @@ static int do_pd_setup(struct fs_enet_private *fep)  {  	struct platform_device *ofdev = to_platform_device(fep->dev); -	fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); +	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);  	if (fep->interrupt == NO_IRQ)  		return -EINVAL; diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c index 22a02a76706..b4bf02f57d4 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c @@ -20,7 +20,6 @@  #include <linux/errno.h>  #include <linux/ioport.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -31,6 +30,8 @@  #include <linux/bitops.h>  #include <linux/fs.h>  #include <linux/platform_device.h> +#include <linux/of_address.h> +#include <linux/of_irq.h>  #include <linux/of_platform.h>  #include <asm/irq.h> @@ -98,7 +99,7 @@ static int do_pd_setup(struct fs_enet_private *fep)  {  	struct platform_device *ofdev = to_platform_device(fep->dev); -	fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); +	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);  	if (fep->interrupt == NO_IRQ)  		return -EINVAL; diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 844ecfa84d1..3d3fde66c2c 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -15,13 +15,13 @@  #include <linux/module.h>  #include <linux/ioport.h>  #include <linux/slab.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h>  #include <linux/mii.h>  #include <linux/platform_device.h>  #include <linux/mdio-bitbang.h> +#include <linux/of_address.h>  #include <linux/of_mdio.h>  #include <linux/of_platform.h> diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 2f1c46a12f0..ebf5d6429a8 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -21,7 +21,6 @@  #include <linux/ioport.h>  #include <linux/slab.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -31,6 +30,7 @@  #include <linux/ethtool.h>  #include <linux/bitops.h>  #include <linux/platform_device.h> +#include <linux/of_address.h>  #include <linux/of_platform.h>  #include <asm/pgtable.h> @@ -95,12 +95,6 @@ static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location,  } -static int fs_enet_fec_mii_reset(struct mii_bus *bus) -{ -	/* nothing here - for now */ -	return 0; -} -  static struct of_device_id fs_enet_mdio_fec_match[];  static int fs_enet_mdio_probe(struct platform_device *ofdev)  { @@ -128,7 +122,6 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)  	new_bus->name = "FEC MII Bus";  	new_bus->read = &fs_enet_fec_mii_read;  	new_bus->write = &fs_enet_fec_mii_write; -	new_bus->reset = &fs_enet_fec_mii_reset;  	ret = of_address_to_resource(ofdev->dev.of_node, 0, &res);  	if (ret) diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index c4f65067cf7..583e71ab7f5 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -20,7 +20,6 @@  #include <linux/string.h>  #include <linux/errno.h>  #include <linux/slab.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/module.h>  #include <linux/mii.h> diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index c4eaadeb572..a6cf40e62f3 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -9,7 +9,7 @@   * Maintainer: Kumar Gala   * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>   * - * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. + * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.   * Copyright 2007 MontaVista Software, Inc.   *   * This program is free software; you can redistribute  it and/or modify it @@ -70,7 +70,6 @@  #include <linux/unistd.h>  #include <linux/slab.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -78,6 +77,8 @@  #include <linux/if_vlan.h>  #include <linux/spinlock.h>  #include <linux/mm.h> +#include <linux/of_address.h> +#include <linux/of_irq.h>  #include <linux/of_mdio.h>  #include <linux/of_platform.h>  #include <linux/ip.h> @@ -88,6 +89,7 @@  #include <asm/io.h>  #include <asm/reg.h> +#include <asm/mpc85xx.h>  #include <asm/irq.h>  #include <asm/uaccess.h>  #include <linux/module.h> @@ -119,7 +121,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id);  static irqreturn_t gfar_transmit(int irq, void *dev_id);  static irqreturn_t gfar_interrupt(int irq, void *dev_id);  static void adjust_link(struct net_device *dev); -static void init_registers(struct net_device *dev); +static noinline void gfar_update_link_state(struct gfar_private *priv);  static int init_phy(struct net_device *dev);  static int gfar_probe(struct platform_device *ofdev);  static int gfar_remove(struct platform_device *ofdev); @@ -127,8 +129,10 @@ static void free_skb_resources(struct gfar_private *priv);  static void gfar_set_multi(struct net_device *dev);  static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);  static void gfar_configure_serdes(struct net_device *dev); -static int gfar_poll(struct napi_struct *napi, int budget); -static int gfar_poll_sq(struct napi_struct *napi, int budget); +static int gfar_poll_rx(struct napi_struct *napi, int budget); +static int gfar_poll_tx(struct napi_struct *napi, int budget); +static int gfar_poll_rx_sq(struct napi_struct *napi, int budget); +static int gfar_poll_tx_sq(struct napi_struct *napi, int budget);  #ifdef CONFIG_NET_POLL_CONTROLLER  static void gfar_netpoll(struct net_device *dev);  #endif @@ -136,9 +140,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);  static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);  static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,  			       int amount_pull, struct napi_struct *napi); -void gfar_halt(struct net_device *dev); -static void gfar_halt_nodisable(struct net_device *dev); -void gfar_start(struct net_device *dev); +static void gfar_halt_nodisable(struct gfar_private *priv);  static void gfar_clear_exact_match(struct net_device *dev);  static void gfar_set_mac_for_addr(struct net_device *dev, int num,  				  const u8 *addr); @@ -330,72 +332,76 @@ static void gfar_init_tx_rx_base(struct gfar_private *priv)  	}  } -static void gfar_init_mac(struct net_device *ndev) +static void gfar_rx_buff_size_config(struct gfar_private *priv)  { -	struct gfar_private *priv = netdev_priv(ndev); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	u32 rctrl = 0; -	u32 tctrl = 0; -	u32 attrs = 0; - -	/* write the tx/rx base registers */ -	gfar_init_tx_rx_base(priv); - -	/* Configure the coalescing support */ -	gfar_configure_coalescing_all(priv); +	int frame_size = priv->ndev->mtu + ETH_HLEN;  	/* set this when rx hw offload (TOE) functions are being used */  	priv->uses_rxfcb = 0; +	if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) +		priv->uses_rxfcb = 1; + +	if (priv->hwts_rx_en) +		priv->uses_rxfcb = 1; + +	if (priv->uses_rxfcb) +		frame_size += GMAC_FCB_LEN; + +	frame_size += priv->padding; + +	frame_size = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) + +		     INCREMENTAL_BUFFER_SIZE; + +	priv->rx_buffer_size = frame_size; +} + +static void gfar_mac_rx_config(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	u32 rctrl = 0; +  	if (priv->rx_filer_enable) {  		rctrl |= RCTRL_FILREN;  		/* Program the RIR0 reg with the required distribution */ -		gfar_write(®s->rir0, DEFAULT_RIR0); +		if (priv->poll_mode == GFAR_SQ_POLLING) +			gfar_write(®s->rir0, DEFAULT_2RXQ_RIR0); +		else /* GFAR_MQ_POLLING */ +			gfar_write(®s->rir0, DEFAULT_8RXQ_RIR0);  	}  	/* Restore PROMISC mode */ -	if (ndev->flags & IFF_PROMISC) +	if (priv->ndev->flags & IFF_PROMISC)  		rctrl |= RCTRL_PROM; -	if (ndev->features & NETIF_F_RXCSUM) { +	if (priv->ndev->features & NETIF_F_RXCSUM)  		rctrl |= RCTRL_CHECKSUMMING; -		priv->uses_rxfcb = 1; -	} - -	if (priv->extended_hash) { -		rctrl |= RCTRL_EXTHASH; -		gfar_clear_exact_match(ndev); -		rctrl |= RCTRL_EMEN; -	} +	if (priv->extended_hash) +		rctrl |= RCTRL_EXTHASH | RCTRL_EMEN;  	if (priv->padding) {  		rctrl &= ~RCTRL_PAL_MASK;  		rctrl |= RCTRL_PADDING(priv->padding);  	} -	/* Insert receive time stamps into padding alignment bytes */ -	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) { -		rctrl &= ~RCTRL_PAL_MASK; -		rctrl |= RCTRL_PADDING(8); -		priv->padding = 8; -	} -  	/* Enable HW time stamping if requested from user space */ -	if (priv->hwts_rx_en) { +	if (priv->hwts_rx_en)  		rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE; -		priv->uses_rxfcb = 1; -	} -	if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX) { +	if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)  		rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; -		priv->uses_rxfcb = 1; -	}  	/* Init rctrl based on our settings */  	gfar_write(®s->rctrl, rctrl); +} -	if (ndev->features & NETIF_F_IP_CSUM) +static void gfar_mac_tx_config(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	u32 tctrl = 0; + +	if (priv->ndev->features & NETIF_F_IP_CSUM)  		tctrl |= TCTRL_INIT_CSUM;  	if (priv->prio_sched_en) @@ -406,30 +412,51 @@ static void gfar_init_mac(struct net_device *ndev)  		gfar_write(®s->tr47wt, DEFAULT_WRRS_WEIGHT);  	} -	gfar_write(®s->tctrl, tctrl); +	if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_TX) +		tctrl |= TCTRL_VLINS; -	/* Set the extraction length and index */ -	attrs = ATTRELI_EL(priv->rx_stash_size) | -		ATTRELI_EI(priv->rx_stash_index); +	gfar_write(®s->tctrl, tctrl); +} -	gfar_write(®s->attreli, attrs); +static void gfar_configure_coalescing(struct gfar_private *priv, +			       unsigned long tx_mask, unsigned long rx_mask) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	u32 __iomem *baddr; -	/* Start with defaults, and add stashing or locking -	 * depending on the approprate variables -	 */ -	attrs = ATTR_INIT_SETTINGS; +	if (priv->mode == MQ_MG_MODE) { +		int i = 0; -	if (priv->bd_stash_en) -		attrs |= ATTR_BDSTASH; +		baddr = ®s->txic0; +		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) { +			gfar_write(baddr + i, 0); +			if (likely(priv->tx_queue[i]->txcoalescing)) +				gfar_write(baddr + i, priv->tx_queue[i]->txic); +		} -	if (priv->rx_stash_size != 0) -		attrs |= ATTR_BUFSTASH; +		baddr = ®s->rxic0; +		for_each_set_bit(i, &rx_mask, priv->num_rx_queues) { +			gfar_write(baddr + i, 0); +			if (likely(priv->rx_queue[i]->rxcoalescing)) +				gfar_write(baddr + i, priv->rx_queue[i]->rxic); +		} +	} else { +		/* Backward compatible case -- even if we enable +		 * multiple queues, there's only single reg to program +		 */ +		gfar_write(®s->txic, 0); +		if (likely(priv->tx_queue[0]->txcoalescing)) +			gfar_write(®s->txic, priv->tx_queue[0]->txic); -	gfar_write(®s->attr, attrs); +		gfar_write(®s->rxic, 0); +		if (unlikely(priv->rx_queue[0]->rxcoalescing)) +			gfar_write(®s->rxic, priv->rx_queue[0]->rxic); +	} +} -	gfar_write(®s->fifo_tx_thr, priv->fifo_threshold); -	gfar_write(®s->fifo_tx_starve, priv->fifo_starve); -	gfar_write(®s->fifo_tx_starve_shutoff, priv->fifo_starve_off); +void gfar_configure_coalescing_all(struct gfar_private *priv) +{ +	gfar_configure_coalescing(priv, 0xFF, 0xFF);  }  static struct net_device_stats *gfar_get_stats(struct net_device *dev) @@ -477,12 +504,27 @@ static const struct net_device_ops gfar_netdev_ops = {  #endif  }; -void lock_rx_qs(struct gfar_private *priv) +static void gfar_ints_disable(struct gfar_private *priv)  {  	int i; +	for (i = 0; i < priv->num_grps; i++) { +		struct gfar __iomem *regs = priv->gfargrp[i].regs; +		/* Clear IEVENT */ +		gfar_write(®s->ievent, IEVENT_INIT_CLEAR); -	for (i = 0; i < priv->num_rx_queues; i++) -		spin_lock(&priv->rx_queue[i]->rxlock); +		/* Initialize IMASK */ +		gfar_write(®s->imask, IMASK_INIT_CLEAR); +	} +} + +static void gfar_ints_enable(struct gfar_private *priv) +{ +	int i; +	for (i = 0; i < priv->num_grps; i++) { +		struct gfar __iomem *regs = priv->gfargrp[i].regs; +		/* Unmask the interrupts we look for */ +		gfar_write(®s->imask, IMASK_DEFAULT); +	}  }  void lock_tx_qs(struct gfar_private *priv) @@ -493,23 +535,50 @@ void lock_tx_qs(struct gfar_private *priv)  		spin_lock(&priv->tx_queue[i]->txlock);  } -void unlock_rx_qs(struct gfar_private *priv) +void unlock_tx_qs(struct gfar_private *priv)  {  	int i; -	for (i = 0; i < priv->num_rx_queues; i++) -		spin_unlock(&priv->rx_queue[i]->rxlock); +	for (i = 0; i < priv->num_tx_queues; i++) +		spin_unlock(&priv->tx_queue[i]->txlock);  } -void unlock_tx_qs(struct gfar_private *priv) +static int gfar_alloc_tx_queues(struct gfar_private *priv)  {  	int i; -	for (i = 0; i < priv->num_tx_queues; i++) -		spin_unlock(&priv->tx_queue[i]->txlock); +	for (i = 0; i < priv->num_tx_queues; i++) { +		priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q), +					    GFP_KERNEL); +		if (!priv->tx_queue[i]) +			return -ENOMEM; + +		priv->tx_queue[i]->tx_skbuff = NULL; +		priv->tx_queue[i]->qindex = i; +		priv->tx_queue[i]->dev = priv->ndev; +		spin_lock_init(&(priv->tx_queue[i]->txlock)); +	} +	return 0;  } -static void free_tx_pointers(struct gfar_private *priv) +static int gfar_alloc_rx_queues(struct gfar_private *priv) +{ +	int i; + +	for (i = 0; i < priv->num_rx_queues; i++) { +		priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q), +					    GFP_KERNEL); +		if (!priv->rx_queue[i]) +			return -ENOMEM; + +		priv->rx_queue[i]->rx_skbuff = NULL; +		priv->rx_queue[i]->qindex = i; +		priv->rx_queue[i]->dev = priv->ndev; +	} +	return 0; +} + +static void gfar_free_tx_queues(struct gfar_private *priv)  {  	int i; @@ -517,7 +586,7 @@ static void free_tx_pointers(struct gfar_private *priv)  		kfree(priv->tx_queue[i]);  } -static void free_rx_pointers(struct gfar_private *priv) +static void gfar_free_rx_queues(struct gfar_private *priv)  {  	int i; @@ -551,23 +620,26 @@ static void disable_napi(struct gfar_private *priv)  {  	int i; -	for (i = 0; i < priv->num_grps; i++) -		napi_disable(&priv->gfargrp[i].napi); +	for (i = 0; i < priv->num_grps; i++) { +		napi_disable(&priv->gfargrp[i].napi_rx); +		napi_disable(&priv->gfargrp[i].napi_tx); +	}  }  static void enable_napi(struct gfar_private *priv)  {  	int i; -	for (i = 0; i < priv->num_grps; i++) -		napi_enable(&priv->gfargrp[i].napi); +	for (i = 0; i < priv->num_grps; i++) { +		napi_enable(&priv->gfargrp[i].napi_rx); +		napi_enable(&priv->gfargrp[i].napi_tx); +	}  }  static int gfar_parse_group(struct device_node *np,  			    struct gfar_private *priv, const char *model)  {  	struct gfar_priv_grp *grp = &priv->gfargrp[priv->num_grps]; -	u32 *queue_mask;  	int i;  	for (i = 0; i < GFAR_NUM_IRQS; i++) { @@ -596,16 +668,52 @@ static int gfar_parse_group(struct device_node *np,  	grp->priv = priv;  	spin_lock_init(&grp->grplock);  	if (priv->mode == MQ_MG_MODE) { -		queue_mask = (u32 *)of_get_property(np, "fsl,rx-bit-map", NULL); -		grp->rx_bit_map = queue_mask ? -			*queue_mask : (DEFAULT_MAPPING >> priv->num_grps); -		queue_mask = (u32 *)of_get_property(np, "fsl,tx-bit-map", NULL); -		grp->tx_bit_map = queue_mask ? -			*queue_mask : (DEFAULT_MAPPING >> priv->num_grps); +		u32 *rxq_mask, *txq_mask; +		rxq_mask = (u32 *)of_get_property(np, "fsl,rx-bit-map", NULL); +		txq_mask = (u32 *)of_get_property(np, "fsl,tx-bit-map", NULL); + +		if (priv->poll_mode == GFAR_SQ_POLLING) { +			/* One Q per interrupt group: Q0 to G0, Q1 to G1 */ +			grp->rx_bit_map = (DEFAULT_MAPPING >> priv->num_grps); +			grp->tx_bit_map = (DEFAULT_MAPPING >> priv->num_grps); +		} else { /* GFAR_MQ_POLLING */ +			grp->rx_bit_map = rxq_mask ? +			*rxq_mask : (DEFAULT_MAPPING >> priv->num_grps); +			grp->tx_bit_map = txq_mask ? +			*txq_mask : (DEFAULT_MAPPING >> priv->num_grps); +		}  	} else {  		grp->rx_bit_map = 0xFF;  		grp->tx_bit_map = 0xFF;  	} + +	/* bit_map's MSB is q0 (from q0 to q7) but, for_each_set_bit parses +	 * right to left, so we need to revert the 8 bits to get the q index +	 */ +	grp->rx_bit_map = bitrev8(grp->rx_bit_map); +	grp->tx_bit_map = bitrev8(grp->tx_bit_map); + +	/* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values, +	 * also assign queues to groups +	 */ +	for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) { +		if (!grp->rx_queue) +			grp->rx_queue = priv->rx_queue[i]; +		grp->num_rx_queues++; +		grp->rstat |= (RSTAT_CLEAR_RHALT >> i); +		priv->rqueue |= ((RQUEUE_EN0 | RQUEUE_EX0) >> i); +		priv->rx_queue[i]->grp = grp; +	} + +	for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) { +		if (!grp->tx_queue) +			grp->tx_queue = priv->tx_queue[i]; +		grp->num_tx_queues++; +		grp->tstat |= (TSTAT_CLEAR_THALT >> i); +		priv->tqueue |= (TQUEUE_EN0 >> i); +		priv->tx_queue[i]->grp = grp; +	} +  	priv->num_grps++;  	return 0; @@ -626,13 +734,45 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  	const u32 *stash_idx;  	unsigned int num_tx_qs, num_rx_qs;  	u32 *tx_queues, *rx_queues; +	unsigned short mode, poll_mode;  	if (!np || !of_device_is_available(np))  		return -ENODEV; -	/* parse the num of tx and rx queues */ +	if (of_device_is_compatible(np, "fsl,etsec2")) { +		mode = MQ_MG_MODE; +		poll_mode = GFAR_SQ_POLLING; +	} else { +		mode = SQ_SG_MODE; +		poll_mode = GFAR_SQ_POLLING; +	} + +	/* parse the num of HW tx and rx queues */  	tx_queues = (u32 *)of_get_property(np, "fsl,num_tx_queues", NULL); -	num_tx_qs = tx_queues ? *tx_queues : 1; +	rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL); + +	if (mode == SQ_SG_MODE) { +		num_tx_qs = 1; +		num_rx_qs = 1; +	} else { /* MQ_MG_MODE */ +		/* get the actual number of supported groups */ +		unsigned int num_grps = of_get_available_child_count(np); + +		if (num_grps == 0 || num_grps > MAXGROUPS) { +			dev_err(&ofdev->dev, "Invalid # of int groups(%d)\n", +				num_grps); +			pr_err("Cannot do alloc_etherdev, aborting\n"); +			return -EINVAL; +		} + +		if (poll_mode == GFAR_SQ_POLLING) { +			num_tx_qs = num_grps; /* one txq per int group */ +			num_rx_qs = num_grps; /* one rxq per int group */ +		} else { /* GFAR_MQ_POLLING */ +			num_tx_qs = tx_queues ? *tx_queues : 1; +			num_rx_qs = rx_queues ? *rx_queues : 1; +		} +	}  	if (num_tx_qs > MAX_TX_QS) {  		pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n", @@ -641,9 +781,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  		return -EINVAL;  	} -	rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL); -	num_rx_qs = rx_queues ? *rx_queues : 1; -  	if (num_rx_qs > MAX_RX_QS) {  		pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",  		       num_rx_qs, MAX_RX_QS); @@ -659,10 +796,20 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  	priv = netdev_priv(dev);  	priv->ndev = dev; +	priv->mode = mode; +	priv->poll_mode = poll_mode; +  	priv->num_tx_queues = num_tx_qs;  	netif_set_real_num_rx_queues(dev, num_rx_qs);  	priv->num_rx_queues = num_rx_qs; -	priv->num_grps = 0x0; + +	err = gfar_alloc_tx_queues(priv); +	if (err) +		goto tx_alloc_failed; + +	err = gfar_alloc_rx_queues(priv); +	if (err) +		goto rx_alloc_failed;  	/* Init Rx queue filer rule set linked list */  	INIT_LIST_HEAD(&priv->rx_list.list); @@ -675,52 +822,18 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  		priv->gfargrp[i].regs = NULL;  	/* Parse and initialize group specific information */ -	if (of_device_is_compatible(np, "fsl,etsec2")) { -		priv->mode = MQ_MG_MODE; +	if (priv->mode == MQ_MG_MODE) {  		for_each_child_of_node(np, child) {  			err = gfar_parse_group(child, priv, model);  			if (err)  				goto err_grp_init;  		} -	} else { -		priv->mode = SQ_SG_MODE; +	} else { /* SQ_SG_MODE */  		err = gfar_parse_group(np, priv, model);  		if (err)  			goto err_grp_init;  	} -	for (i = 0; i < priv->num_tx_queues; i++) -		priv->tx_queue[i] = NULL; -	for (i = 0; i < priv->num_rx_queues; i++) -		priv->rx_queue[i] = NULL; - -	for (i = 0; i < priv->num_tx_queues; i++) { -		priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q), -					    GFP_KERNEL); -		if (!priv->tx_queue[i]) { -			err = -ENOMEM; -			goto tx_alloc_failed; -		} -		priv->tx_queue[i]->tx_skbuff = NULL; -		priv->tx_queue[i]->qindex = i; -		priv->tx_queue[i]->dev = dev; -		spin_lock_init(&(priv->tx_queue[i]->txlock)); -	} - -	for (i = 0; i < priv->num_rx_queues; i++) { -		priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q), -					    GFP_KERNEL); -		if (!priv->rx_queue[i]) { -			err = -ENOMEM; -			goto rx_alloc_failed; -		} -		priv->rx_queue[i]->rx_skbuff = NULL; -		priv->rx_queue[i]->qindex = i; -		priv->rx_queue[i]->dev = dev; -		spin_lock_init(&(priv->rx_queue[i]->rxlock)); -	} - -  	stash = of_get_property(np, "bd-stash", NULL);  	if (stash) { @@ -747,17 +860,16 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  		memcpy(dev->dev_addr, mac_addr, ETH_ALEN);  	if (model && !strcasecmp(model, "TSEC")) -		priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | +		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |  				     FSL_GIANFAR_DEV_HAS_COALESCE |  				     FSL_GIANFAR_DEV_HAS_RMON |  				     FSL_GIANFAR_DEV_HAS_MULTI_INTR;  	if (model && !strcasecmp(model, "eTSEC")) -		priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | +		priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |  				     FSL_GIANFAR_DEV_HAS_COALESCE |  				     FSL_GIANFAR_DEV_HAS_RMON |  				     FSL_GIANFAR_DEV_HAS_MULTI_INTR | -				     FSL_GIANFAR_DEV_HAS_PADDING |  				     FSL_GIANFAR_DEV_HAS_CSUM |  				     FSL_GIANFAR_DEV_HAS_VLAN |  				     FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | @@ -777,23 +889,33 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  	priv->phy_node = of_parse_phandle(np, "phy-handle", 0); +	/* In the case of a fixed PHY, the DT node associated +	 * to the PHY is the Ethernet MAC DT node. +	 */ +	if (of_phy_is_fixed_link(np)) { +		err = of_phy_register_fixed_link(np); +		if (err) +			goto err_grp_init; + +		priv->phy_node = np; +	} +  	/* Find the TBI PHY.  If it's not there, we don't support SGMII */  	priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);  	return 0; -rx_alloc_failed: -	free_rx_pointers(priv); -tx_alloc_failed: -	free_tx_pointers(priv);  err_grp_init:  	unmap_group_regs(priv); +rx_alloc_failed: +	gfar_free_rx_queues(priv); +tx_alloc_failed: +	gfar_free_tx_queues(priv);  	free_gfar_dev(priv);  	return err;  } -static int gfar_hwtstamp_ioctl(struct net_device *netdev, -			       struct ifreq *ifr, int cmd) +static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)  {  	struct hwtstamp_config config;  	struct gfar_private *priv = netdev_priv(netdev); @@ -821,18 +943,16 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,  	switch (config.rx_filter) {  	case HWTSTAMP_FILTER_NONE:  		if (priv->hwts_rx_en) { -			stop_gfar(netdev);  			priv->hwts_rx_en = 0; -			startup_gfar(netdev); +			reset_gfar(netdev);  		}  		break;  	default:  		if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))  			return -ERANGE;  		if (!priv->hwts_rx_en) { -			stop_gfar(netdev);  			priv->hwts_rx_en = 1; -			startup_gfar(netdev); +			reset_gfar(netdev);  		}  		config.rx_filter = HWTSTAMP_FILTER_ALL;  		break; @@ -842,7 +962,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,  		-EFAULT : 0;  } -/* Ioctl MII Interface */ +static int gfar_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) +{ +	struct hwtstamp_config config; +	struct gfar_private *priv = netdev_priv(netdev); + +	config.flags = 0; +	config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; +	config.rx_filter = (priv->hwts_rx_en ? +			    HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE); + +	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? +		-EFAULT : 0; +} +  static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  {  	struct gfar_private *priv = netdev_priv(dev); @@ -851,7 +984,9 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  		return -EINVAL;  	if (cmd == SIOCSHWTSTAMP) -		return gfar_hwtstamp_ioctl(dev, rq, cmd); +		return gfar_hwtstamp_set(dev, rq); +	if (cmd == SIOCGHWTSTAMP) +		return gfar_hwtstamp_get(dev, rq);  	if (!priv->phydev)  		return -ENODEV; @@ -859,19 +994,6 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  	return phy_mii_ioctl(priv->phydev, rq, cmd);  } -static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs) -{ -	unsigned int new_bit_map = 0x0; -	int mask = 0x1 << (max_qs - 1), i; - -	for (i = 0; i < max_qs; i++) { -		if (bit_map & mask) -			new_bit_map = new_bit_map + (1 << i); -		mask = mask >> 0x1; -	} -	return new_bit_map; -} -  static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar,  				   u32 class)  { @@ -939,9 +1061,8 @@ static void gfar_init_filer_table(struct gfar_private *priv)  	}  } -static void gfar_detect_errata(struct gfar_private *priv) +static void __gfar_detect_errata_83xx(struct gfar_private *priv)  { -	struct device *dev = &priv->ofdev->dev;  	unsigned int pvr = mfspr(SPRN_PVR);  	unsigned int svr = mfspr(SPRN_SVR);  	unsigned int mod = (svr >> 16) & 0xfff6; /* w/o E suffix */ @@ -957,114 +1078,173 @@ static void gfar_detect_errata(struct gfar_private *priv)  	    (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))  		priv->errata |= GFAR_ERRATA_76; -	/* MPC8313 and MPC837x all rev */ -	if ((pvr == 0x80850010 && mod == 0x80b0) || -	    (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) -		priv->errata |= GFAR_ERRATA_A002; - -	/* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */ -	if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) || -	    (pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020)) +	/* MPC8313 Rev < 2.0 */ +	if (pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020)  		priv->errata |= GFAR_ERRATA_12; - -	if (priv->errata) -		dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", -			 priv->errata);  } -/* Set up the ethernet device structure, private data, - * and anything else we need before we start - */ -static int gfar_probe(struct platform_device *ofdev) +static void __gfar_detect_errata_85xx(struct gfar_private *priv)  { -	u32 tempval; -	struct net_device *dev = NULL; -	struct gfar_private *priv = NULL; -	struct gfar __iomem *regs = NULL; -	int err = 0, i, grp_idx = 0; -	u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0; -	u32 isrg = 0; -	u32 __iomem *baddr; - -	err = gfar_of_init(ofdev, &dev); +	unsigned int svr = mfspr(SPRN_SVR); -	if (err) -		return err; +	if ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) == 0x20)) +		priv->errata |= GFAR_ERRATA_12; +	if (((SVR_SOC_VER(svr) == SVR_P2020) && (SVR_REV(svr) < 0x20)) || +	    ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20))) +		priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */ +} -	priv = netdev_priv(dev); -	priv->ndev = dev; -	priv->ofdev = ofdev; -	priv->dev = &ofdev->dev; -	SET_NETDEV_DEV(dev, &ofdev->dev); +static void gfar_detect_errata(struct gfar_private *priv) +{ +	struct device *dev = &priv->ofdev->dev; -	spin_lock_init(&priv->bflock); -	INIT_WORK(&priv->reset_task, gfar_reset_task); +	/* no plans to fix */ +	priv->errata |= GFAR_ERRATA_A002; -	platform_set_drvdata(ofdev, priv); -	regs = priv->gfargrp[0].regs; +	if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2)) +		__gfar_detect_errata_85xx(priv); +	else /* non-mpc85xx parts, i.e. e300 core based */ +		__gfar_detect_errata_83xx(priv); -	gfar_detect_errata(priv); +	if (priv->errata) +		dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", +			 priv->errata); +} -	/* Stop the DMA engine now, in case it was running before -	 * (The firmware could have used it, and left it running). -	 */ -	gfar_halt(dev); +void gfar_mac_reset(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	u32 tempval;  	/* Reset MAC layer */  	gfar_write(®s->maccfg1, MACCFG1_SOFT_RESET);  	/* We need to delay at least 3 TX clocks */ -	udelay(2); +	udelay(3); -	tempval = 0; -	if (!priv->pause_aneg_en && priv->tx_pause_en) -		tempval |= MACCFG1_TX_FLOW; -	if (!priv->pause_aneg_en && priv->rx_pause_en) -		tempval |= MACCFG1_RX_FLOW;  	/* the soft reset bit is not self-resetting, so we need to  	 * clear it before resuming normal operation  	 */ -	gfar_write(®s->maccfg1, tempval); +	gfar_write(®s->maccfg1, 0); + +	udelay(3); + +	/* Compute rx_buff_size based on config flags */ +	gfar_rx_buff_size_config(priv); + +	/* Initialize the max receive frame/buffer lengths */ +	gfar_write(®s->maxfrm, priv->rx_buffer_size); +	gfar_write(®s->mrblr, priv->rx_buffer_size); + +	/* Initialize the Minimum Frame Length Register */ +	gfar_write(®s->minflr, MINFLR_INIT_SETTINGS);  	/* Initialize MACCFG2. */  	tempval = MACCFG2_INIT_SETTINGS; -	if (gfar_has_errata(priv, GFAR_ERRATA_74)) + +	/* If the mtu is larger than the max size for standard +	 * ethernet frames (ie, a jumbo frame), then set maccfg2 +	 * to allow huge frames, and to check the length +	 */ +	if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE || +	    gfar_has_errata(priv, GFAR_ERRATA_74))  		tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK; +  	gfar_write(®s->maccfg2, tempval); +	/* Clear mac addr hash registers */ +	gfar_write(®s->igaddr0, 0); +	gfar_write(®s->igaddr1, 0); +	gfar_write(®s->igaddr2, 0); +	gfar_write(®s->igaddr3, 0); +	gfar_write(®s->igaddr4, 0); +	gfar_write(®s->igaddr5, 0); +	gfar_write(®s->igaddr6, 0); +	gfar_write(®s->igaddr7, 0); + +	gfar_write(®s->gaddr0, 0); +	gfar_write(®s->gaddr1, 0); +	gfar_write(®s->gaddr2, 0); +	gfar_write(®s->gaddr3, 0); +	gfar_write(®s->gaddr4, 0); +	gfar_write(®s->gaddr5, 0); +	gfar_write(®s->gaddr6, 0); +	gfar_write(®s->gaddr7, 0); + +	if (priv->extended_hash) +		gfar_clear_exact_match(priv->ndev); + +	gfar_mac_rx_config(priv); + +	gfar_mac_tx_config(priv); + +	gfar_set_mac_address(priv->ndev); + +	gfar_set_multi(priv->ndev); + +	/* clear ievent and imask before configuring coalescing */ +	gfar_ints_disable(priv); + +	/* Configure the coalescing support */ +	gfar_configure_coalescing_all(priv); +} + +static void gfar_hw_init(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	u32 attrs; + +	/* Stop the DMA engine now, in case it was running before +	 * (The firmware could have used it, and left it running). +	 */ +	gfar_halt(priv); + +	gfar_mac_reset(priv); + +	/* Zero out the rmon mib registers if it has them */ +	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { +		memset_io(&(regs->rmon), 0, sizeof(struct rmon_mib)); + +		/* Mask off the CAM interrupts */ +		gfar_write(®s->rmon.cam1, 0xffffffff); +		gfar_write(®s->rmon.cam2, 0xffffffff); +	} +  	/* Initialize ECNTRL */  	gfar_write(®s->ecntrl, ECNTRL_INIT_SETTINGS); -	/* Set the dev->base_addr to the gfar reg region */ -	dev->base_addr = (unsigned long) regs; +	/* Set the extraction length and index */ +	attrs = ATTRELI_EL(priv->rx_stash_size) | +		ATTRELI_EI(priv->rx_stash_index); -	/* Fill in the dev structure */ -	dev->watchdog_timeo = TX_TIMEOUT; -	dev->mtu = 1500; -	dev->netdev_ops = &gfar_netdev_ops; -	dev->ethtool_ops = &gfar_ethtool_ops; +	gfar_write(®s->attreli, attrs); -	/* Register for napi ...We are registering NAPI for each grp */ -	if (priv->mode == SQ_SG_MODE) -		netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq, -			       GFAR_DEV_WEIGHT); -	else -		for (i = 0; i < priv->num_grps; i++) -			netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll, -				       GFAR_DEV_WEIGHT); +	/* Start with defaults, and add stashing +	 * depending on driver parameters +	 */ +	attrs = ATTR_INIT_SETTINGS; -	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { -		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | -				   NETIF_F_RXCSUM; -		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | -				 NETIF_F_RXCSUM | NETIF_F_HIGHDMA; -	} +	if (priv->bd_stash_en) +		attrs |= ATTR_BDSTASH; -	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { -		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | -				    NETIF_F_HW_VLAN_CTAG_RX; -		dev->features |= NETIF_F_HW_VLAN_CTAG_RX; -	} +	if (priv->rx_stash_size != 0) +		attrs |= ATTR_BUFSTASH; + +	gfar_write(®s->attr, attrs); + +	/* FIFO configs */ +	gfar_write(®s->fifo_tx_thr, DEFAULT_FIFO_TX_THR); +	gfar_write(®s->fifo_tx_starve, DEFAULT_FIFO_TX_STARVE); +	gfar_write(®s->fifo_tx_starve_shutoff, DEFAULT_FIFO_TX_STARVE_OFF); + +	/* Program the interrupt steering regs, only for MG devices */ +	if (priv->num_grps > 1) +		gfar_write_isrg(priv); +} + +static void gfar_init_addr_hash_table(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs;  	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {  		priv->extended_hash = 1; @@ -1100,68 +1280,81 @@ static int gfar_probe(struct platform_device *ofdev)  		priv->hash_regs[6] = ®s->gaddr6;  		priv->hash_regs[7] = ®s->gaddr7;  	} +} -	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING) -		priv->padding = DEFAULT_PADDING; -	else -		priv->padding = 0; +/* Set up the ethernet device structure, private data, + * and anything else we need before we start + */ +static int gfar_probe(struct platform_device *ofdev) +{ +	struct net_device *dev = NULL; +	struct gfar_private *priv = NULL; +	int err = 0, i; -	if (dev->features & NETIF_F_IP_CSUM || -	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) -		dev->needed_headroom = GMAC_FCB_LEN; +	err = gfar_of_init(ofdev, &dev); -	/* Program the isrg regs only if number of grps > 1 */ -	if (priv->num_grps > 1) { -		baddr = ®s->isrg0; -		for (i = 0; i < priv->num_grps; i++) { -			isrg |= (priv->gfargrp[i].rx_bit_map << ISRG_SHIFT_RX); -			isrg |= (priv->gfargrp[i].tx_bit_map << ISRG_SHIFT_TX); -			gfar_write(baddr, isrg); -			baddr++; -			isrg = 0x0; +	if (err) +		return err; + +	priv = netdev_priv(dev); +	priv->ndev = dev; +	priv->ofdev = ofdev; +	priv->dev = &ofdev->dev; +	SET_NETDEV_DEV(dev, &ofdev->dev); + +	spin_lock_init(&priv->bflock); +	INIT_WORK(&priv->reset_task, gfar_reset_task); + +	platform_set_drvdata(ofdev, priv); + +	gfar_detect_errata(priv); + +	/* Set the dev->base_addr to the gfar reg region */ +	dev->base_addr = (unsigned long) priv->gfargrp[0].regs; + +	/* Fill in the dev structure */ +	dev->watchdog_timeo = TX_TIMEOUT; +	dev->mtu = 1500; +	dev->netdev_ops = &gfar_netdev_ops; +	dev->ethtool_ops = &gfar_ethtool_ops; + +	/* Register for napi ...We are registering NAPI for each grp */ +	for (i = 0; i < priv->num_grps; i++) { +		if (priv->poll_mode == GFAR_SQ_POLLING) { +			netif_napi_add(dev, &priv->gfargrp[i].napi_rx, +				       gfar_poll_rx_sq, GFAR_DEV_WEIGHT); +			netif_napi_add(dev, &priv->gfargrp[i].napi_tx, +				       gfar_poll_tx_sq, 2); +		} else { +			netif_napi_add(dev, &priv->gfargrp[i].napi_rx, +				       gfar_poll_rx, GFAR_DEV_WEIGHT); +			netif_napi_add(dev, &priv->gfargrp[i].napi_tx, +				       gfar_poll_tx, 2);  		}  	} -	/* Need to reverse the bit maps as  bit_map's MSB is q0 -	 * but, for_each_set_bit parses from right to left, which -	 * basically reverses the queue numbers -	 */ -	for (i = 0; i< priv->num_grps; i++) { -		priv->gfargrp[i].tx_bit_map = -			reverse_bitmap(priv->gfargrp[i].tx_bit_map, MAX_TX_QS); -		priv->gfargrp[i].rx_bit_map = -			reverse_bitmap(priv->gfargrp[i].rx_bit_map, MAX_RX_QS); +	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { +		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | +				   NETIF_F_RXCSUM; +		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | +				 NETIF_F_RXCSUM | NETIF_F_HIGHDMA;  	} -	/* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values, -	 * also assign queues to groups -	 */ -	for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) { -		priv->gfargrp[grp_idx].num_rx_queues = 0x0; - -		for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map, -				 priv->num_rx_queues) { -			priv->gfargrp[grp_idx].num_rx_queues++; -			priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx]; -			rstat = rstat | (RSTAT_CLEAR_RHALT >> i); -			rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i); -		} -		priv->gfargrp[grp_idx].num_tx_queues = 0x0; - -		for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map, -				 priv->num_tx_queues) { -			priv->gfargrp[grp_idx].num_tx_queues++; -			priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx]; -			tstat = tstat | (TSTAT_CLEAR_THALT >> i); -			tqueue = tqueue | (TQUEUE_EN0 >> i); -		} -		priv->gfargrp[grp_idx].rstat = rstat; -		priv->gfargrp[grp_idx].tstat = tstat; -		rstat = tstat =0; +	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { +		dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | +				    NETIF_F_HW_VLAN_CTAG_RX; +		dev->features |= NETIF_F_HW_VLAN_CTAG_RX;  	} -	gfar_write(®s->rqueue, rqueue); -	gfar_write(®s->tqueue, tqueue); +	gfar_init_addr_hash_table(priv); + +	/* Insert receive time stamps into padding alignment bytes */ +	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) +		priv->padding = 8; + +	if (dev->features & NETIF_F_IP_CSUM || +	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) +		dev->needed_headroom = GMAC_FCB_LEN;  	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; @@ -1187,6 +1380,10 @@ static int gfar_probe(struct platform_device *ofdev)  	if (priv->num_tx_queues == 1)  		priv->prio_sched_en = 1; +	set_bit(GFAR_DOWN, &priv->state); + +	gfar_hw_init(priv); +  	/* Carrier starts down, phylib will bring it up */  	netif_carrier_off(dev); @@ -1218,9 +1415,6 @@ static int gfar_probe(struct platform_device *ofdev)  	/* Initialize the filer table */  	gfar_init_filer_table(priv); -	/* Create all the sysfs files */ -	gfar_init_sysfs(dev); -  	/* Print out the device info */  	netdev_info(dev, "mac: %pM\n", dev->dev_addr); @@ -1239,8 +1433,8 @@ static int gfar_probe(struct platform_device *ofdev)  register_fail:  	unmap_group_regs(priv); -	free_tx_pointers(priv); -	free_rx_pointers(priv); +	gfar_free_rx_queues(priv); +	gfar_free_tx_queues(priv);  	if (priv->phy_node)  		of_node_put(priv->phy_node);  	if (priv->tbi_node) @@ -1260,6 +1454,8 @@ static int gfar_remove(struct platform_device *ofdev)  	unregister_netdev(priv->ndev);  	unmap_group_regs(priv); +	gfar_free_rx_queues(priv); +	gfar_free_tx_queues(priv);  	free_gfar_dev(priv);  	return 0; @@ -1285,9 +1481,8 @@ static int gfar_suspend(struct device *dev)  		local_irq_save(flags);  		lock_tx_qs(priv); -		lock_rx_qs(priv); -		gfar_halt_nodisable(ndev); +		gfar_halt_nodisable(priv);  		/* Disable Tx, and Rx if wake-on-LAN is disabled. */  		tempval = gfar_read(®s->maccfg1); @@ -1299,7 +1494,6 @@ static int gfar_suspend(struct device *dev)  		gfar_write(®s->maccfg1, tempval); -		unlock_rx_qs(priv);  		unlock_tx_qs(priv);  		local_irq_restore(flags); @@ -1345,15 +1539,13 @@ static int gfar_resume(struct device *dev)  	 */  	local_irq_save(flags);  	lock_tx_qs(priv); -	lock_rx_qs(priv);  	tempval = gfar_read(®s->maccfg2);  	tempval &= ~MACCFG2_MPEN;  	gfar_write(®s->maccfg2, tempval); -	gfar_start(ndev); +	gfar_start(priv); -	unlock_rx_qs(priv);  	unlock_tx_qs(priv);  	local_irq_restore(flags); @@ -1380,10 +1572,11 @@ static int gfar_restore(struct device *dev)  		return -ENOMEM;  	} -	init_registers(ndev); -	gfar_set_mac_address(ndev); -	gfar_init_mac(ndev); -	gfar_start(ndev); +	gfar_mac_reset(priv); + +	gfar_init_tx_rx_base(priv); + +	gfar_start(priv);  	priv->oldlink = 0;  	priv->oldspeed = 0; @@ -1478,9 +1671,6 @@ static int init_phy(struct net_device *dev)  	priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0,  				      interface); -	if (!priv->phydev) -		priv->phydev = of_phy_connect_fixed_link(dev, &adjust_link, -							 interface);  	if (!priv->phydev) {  		dev_err(&dev->dev, "could not attach to PHY\n");  		return -ENODEV; @@ -1541,57 +1731,6 @@ static void gfar_configure_serdes(struct net_device *dev)  		  BMCR_SPEED1000);  } -static void init_registers(struct net_device *dev) -{ -	struct gfar_private *priv = netdev_priv(dev); -	struct gfar __iomem *regs = NULL; -	int i; - -	for (i = 0; i < priv->num_grps; i++) { -		regs = priv->gfargrp[i].regs; -		/* Clear IEVENT */ -		gfar_write(®s->ievent, IEVENT_INIT_CLEAR); - -		/* Initialize IMASK */ -		gfar_write(®s->imask, IMASK_INIT_CLEAR); -	} - -	regs = priv->gfargrp[0].regs; -	/* Init hash registers to zero */ -	gfar_write(®s->igaddr0, 0); -	gfar_write(®s->igaddr1, 0); -	gfar_write(®s->igaddr2, 0); -	gfar_write(®s->igaddr3, 0); -	gfar_write(®s->igaddr4, 0); -	gfar_write(®s->igaddr5, 0); -	gfar_write(®s->igaddr6, 0); -	gfar_write(®s->igaddr7, 0); - -	gfar_write(®s->gaddr0, 0); -	gfar_write(®s->gaddr1, 0); -	gfar_write(®s->gaddr2, 0); -	gfar_write(®s->gaddr3, 0); -	gfar_write(®s->gaddr4, 0); -	gfar_write(®s->gaddr5, 0); -	gfar_write(®s->gaddr6, 0); -	gfar_write(®s->gaddr7, 0); - -	/* Zero out the rmon mib registers if it has them */ -	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { -		memset_io(&(regs->rmon), 0, sizeof (struct rmon_mib)); - -		/* Mask off the CAM interrupts */ -		gfar_write(®s->rmon.cam1, 0xffffffff); -		gfar_write(®s->rmon.cam2, 0xffffffff); -	} - -	/* Initialize the max receive buffer length */ -	gfar_write(®s->mrblr, priv->rx_buffer_size); - -	/* Initialize the Minimum Frame Length Register */ -	gfar_write(®s->minflr, MINFLR_INIT_SETTINGS); -} -  static int __gfar_is_rx_idle(struct gfar_private *priv)  {  	u32 res; @@ -1599,7 +1738,7 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)  	/* Normaly TSEC should not hang on GRS commands, so we should  	 * actually wait for IEVENT_GRSC flag.  	 */ -	if (likely(!gfar_has_errata(priv, GFAR_ERRATA_A002))) +	if (!gfar_has_errata(priv, GFAR_ERRATA_A002))  		return 0;  	/* Read the eTSEC register at offset 0xD1C. If bits 7-14 are @@ -1615,23 +1754,13 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)  }  /* Halt the receive and transmit queues */ -static void gfar_halt_nodisable(struct net_device *dev) +static void gfar_halt_nodisable(struct gfar_private *priv)  { -	struct gfar_private *priv = netdev_priv(dev); -	struct gfar __iomem *regs = NULL; +	struct gfar __iomem *regs = priv->gfargrp[0].regs;  	u32 tempval; -	int i; -	for (i = 0; i < priv->num_grps; i++) { -		regs = priv->gfargrp[i].regs; -		/* Mask all interrupts */ -		gfar_write(®s->imask, IMASK_INIT_CLEAR); - -		/* Clear all interrupts */ -		gfar_write(®s->ievent, IEVENT_INIT_CLEAR); -	} +	gfar_ints_disable(priv); -	regs = priv->gfargrp[0].regs;  	/* Stop the DMA, and wait for it to stop */  	tempval = gfar_read(®s->dmactrl);  	if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) != @@ -1652,56 +1781,41 @@ static void gfar_halt_nodisable(struct net_device *dev)  }  /* Halt the receive and transmit queues */ -void gfar_halt(struct net_device *dev) +void gfar_halt(struct gfar_private *priv)  { -	struct gfar_private *priv = netdev_priv(dev);  	struct gfar __iomem *regs = priv->gfargrp[0].regs;  	u32 tempval; -	gfar_halt_nodisable(dev); +	/* Dissable the Rx/Tx hw queues */ +	gfar_write(®s->rqueue, 0); +	gfar_write(®s->tqueue, 0); + +	mdelay(10); + +	gfar_halt_nodisable(priv); -	/* Disable Rx and Tx */ +	/* Disable Rx/Tx DMA */  	tempval = gfar_read(®s->maccfg1);  	tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);  	gfar_write(®s->maccfg1, tempval);  } -static void free_grp_irqs(struct gfar_priv_grp *grp) -{ -	free_irq(gfar_irq(grp, TX)->irq, grp); -	free_irq(gfar_irq(grp, RX)->irq, grp); -	free_irq(gfar_irq(grp, ER)->irq, grp); -} -  void stop_gfar(struct net_device *dev)  {  	struct gfar_private *priv = netdev_priv(dev); -	unsigned long flags; -	int i; - -	phy_stop(priv->phydev); +	netif_tx_stop_all_queues(dev); -	/* Lock it down */ -	local_irq_save(flags); -	lock_tx_qs(priv); -	lock_rx_qs(priv); +	smp_mb__before_atomic(); +	set_bit(GFAR_DOWN, &priv->state); +	smp_mb__after_atomic(); -	gfar_halt(dev); +	disable_napi(priv); -	unlock_rx_qs(priv); -	unlock_tx_qs(priv); -	local_irq_restore(flags); +	/* disable ints and gracefully shut down Rx/Tx DMA */ +	gfar_halt(priv); -	/* Free the IRQs */ -	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { -		for (i = 0; i < priv->num_grps; i++) -			free_grp_irqs(&priv->gfargrp[i]); -	} else { -		for (i = 0; i < priv->num_grps; i++) -			free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq, -				 &priv->gfargrp[i]); -	} +	phy_stop(priv->phydev);  	free_skb_resources(priv);  } @@ -1792,17 +1906,15 @@ static void free_skb_resources(struct gfar_private *priv)  			  priv->tx_queue[0]->tx_bd_dma_base);  } -void gfar_start(struct net_device *dev) +void gfar_start(struct gfar_private *priv)  { -	struct gfar_private *priv = netdev_priv(dev);  	struct gfar __iomem *regs = priv->gfargrp[0].regs;  	u32 tempval;  	int i = 0; -	/* Enable Rx and Tx in MACCFG1 */ -	tempval = gfar_read(®s->maccfg1); -	tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); -	gfar_write(®s->maccfg1, tempval); +	/* Enable Rx/Tx hw queues */ +	gfar_write(®s->rqueue, priv->rqueue); +	gfar_write(®s->tqueue, priv->tqueue);  	/* Initialize DMACTRL to have WWR and WOP */  	tempval = gfar_read(®s->dmactrl); @@ -1819,52 +1931,23 @@ void gfar_start(struct net_device *dev)  		/* Clear THLT/RHLT, so that the DMA starts polling now */  		gfar_write(®s->tstat, priv->gfargrp[i].tstat);  		gfar_write(®s->rstat, priv->gfargrp[i].rstat); -		/* Unmask the interrupts we look for */ -		gfar_write(®s->imask, IMASK_DEFAULT);  	} -	dev->trans_start = jiffies; /* prevent tx timeout */ -} - -static void gfar_configure_coalescing(struct gfar_private *priv, -			       unsigned long tx_mask, unsigned long rx_mask) -{ -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	u32 __iomem *baddr; - -	if (priv->mode == MQ_MG_MODE) { -		int i = 0; +	/* Enable Rx/Tx DMA */ +	tempval = gfar_read(®s->maccfg1); +	tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN); +	gfar_write(®s->maccfg1, tempval); -		baddr = ®s->txic0; -		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) { -			gfar_write(baddr + i, 0); -			if (likely(priv->tx_queue[i]->txcoalescing)) -				gfar_write(baddr + i, priv->tx_queue[i]->txic); -		} +	gfar_ints_enable(priv); -		baddr = ®s->rxic0; -		for_each_set_bit(i, &rx_mask, priv->num_rx_queues) { -			gfar_write(baddr + i, 0); -			if (likely(priv->rx_queue[i]->rxcoalescing)) -				gfar_write(baddr + i, priv->rx_queue[i]->rxic); -		} -	} else { -		/* Backward compatible case -- even if we enable -		 * multiple queues, there's only single reg to program -		 */ -		gfar_write(®s->txic, 0); -		if (likely(priv->tx_queue[0]->txcoalescing)) -			gfar_write(®s->txic, priv->tx_queue[0]->txic); - -		gfar_write(®s->rxic, 0); -		if (unlikely(priv->rx_queue[0]->rxcoalescing)) -			gfar_write(®s->rxic, priv->rx_queue[0]->rxic); -	} +	priv->ndev->trans_start = jiffies; /* prevent tx timeout */  } -void gfar_configure_coalescing_all(struct gfar_private *priv) +static void free_grp_irqs(struct gfar_priv_grp *grp)  { -	gfar_configure_coalescing(priv, 0xFF, 0xFF); +	free_irq(gfar_irq(grp, TX)->irq, grp); +	free_irq(gfar_irq(grp, RX)->irq, grp); +	free_irq(gfar_irq(grp, ER)->irq, grp);  }  static int register_grp_irqs(struct gfar_priv_grp *grp) @@ -1923,46 +2006,65 @@ err_irq_fail:  } -/* Bring the controller up and running */ -int startup_gfar(struct net_device *ndev) +static void gfar_free_irq(struct gfar_private *priv)  { -	struct gfar_private *priv = netdev_priv(ndev); -	struct gfar __iomem *regs = NULL; -	int err, i, j; +	int i; -	for (i = 0; i < priv->num_grps; i++) { -		regs= priv->gfargrp[i].regs; -		gfar_write(®s->imask, IMASK_INIT_CLEAR); +	/* Free the IRQs */ +	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { +		for (i = 0; i < priv->num_grps; i++) +			free_grp_irqs(&priv->gfargrp[i]); +	} else { +		for (i = 0; i < priv->num_grps; i++) +			free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq, +				 &priv->gfargrp[i]);  	} +} -	regs= priv->gfargrp[0].regs; -	err = gfar_alloc_skb_resources(ndev); -	if (err) -		return err; - -	gfar_init_mac(ndev); +static int gfar_request_irq(struct gfar_private *priv) +{ +	int err, i, j;  	for (i = 0; i < priv->num_grps; i++) {  		err = register_grp_irqs(&priv->gfargrp[i]);  		if (err) {  			for (j = 0; j < i; j++)  				free_grp_irqs(&priv->gfargrp[j]); -			goto irq_fail; +			return err;  		}  	} -	/* Start the controller */ -	gfar_start(ndev); +	return 0; +} + +/* Bring the controller up and running */ +int startup_gfar(struct net_device *ndev) +{ +	struct gfar_private *priv = netdev_priv(ndev); +	int err; + +	gfar_mac_reset(priv); + +	err = gfar_alloc_skb_resources(ndev); +	if (err) +		return err; + +	gfar_init_tx_rx_base(priv); + +	smp_mb__before_atomic(); +	clear_bit(GFAR_DOWN, &priv->state); +	smp_mb__after_atomic(); + +	/* Start Rx/Tx DMA and enable the interrupts */ +	gfar_start(priv);  	phy_start(priv->phydev); -	gfar_configure_coalescing_all(priv); +	enable_napi(priv); -	return 0; +	netif_tx_wake_all_queues(ndev); -irq_fail: -	free_skb_resources(priv); -	return err; +	return 0;  }  /* Called when something needs to use the ethernet device @@ -1973,27 +2075,17 @@ static int gfar_enet_open(struct net_device *dev)  	struct gfar_private *priv = netdev_priv(dev);  	int err; -	enable_napi(priv); - -	/* Initialize a bunch of registers */ -	init_registers(dev); - -	gfar_set_mac_address(dev); -  	err = init_phy(dev); +	if (err) +		return err; -	if (err) { -		disable_napi(priv); +	err = gfar_request_irq(priv); +	if (err)  		return err; -	}  	err = startup_gfar(dev); -	if (err) { -		disable_napi(priv); +	if (err)  		return err; -	} - -	netif_tx_start_all_queues(dev);  	device_set_wakeup_enable(&dev->dev, priv->wol_en); @@ -2119,13 +2211,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)  		skb_new = skb_realloc_headroom(skb, fcb_len);  		if (!skb_new) {  			dev->stats.tx_errors++; -			kfree_skb(skb); +			dev_kfree_skb_any(skb);  			return NETDEV_TX_OK;  		}  		if (skb->sk)  			skb_set_owner_w(skb_new, skb->sk); -		consume_skb(skb); +		dev_consume_skb_any(skb);  		skb = skb_new;  	} @@ -2318,8 +2410,6 @@ static int gfar_close(struct net_device *dev)  {  	struct gfar_private *priv = netdev_priv(dev); -	disable_napi(priv); -  	cancel_work_sync(&priv->reset_task);  	stop_gfar(dev); @@ -2327,7 +2417,7 @@ static int gfar_close(struct net_device *dev)  	phy_disconnect(priv->phydev);  	priv->phydev = NULL; -	netif_tx_stop_all_queues(dev); +	gfar_free_irq(priv);  	return 0;  } @@ -2340,77 +2430,9 @@ static int gfar_set_mac_address(struct net_device *dev)  	return 0;  } -/* Check if rx parser should be activated */ -void gfar_check_rx_parser_mode(struct gfar_private *priv) -{ -	struct gfar __iomem *regs; -	u32 tempval; - -	regs = priv->gfargrp[0].regs; - -	tempval = gfar_read(®s->rctrl); -	/* If parse is no longer required, then disable parser */ -	if (tempval & RCTRL_REQ_PARSER) { -		tempval |= RCTRL_PRSDEP_INIT; -		priv->uses_rxfcb = 1; -	} else { -		tempval &= ~RCTRL_PRSDEP_INIT; -		priv->uses_rxfcb = 0; -	} -	gfar_write(®s->rctrl, tempval); -} - -/* Enables and disables VLAN insertion/extraction */ -void gfar_vlan_mode(struct net_device *dev, netdev_features_t features) -{ -	struct gfar_private *priv = netdev_priv(dev); -	struct gfar __iomem *regs = NULL; -	unsigned long flags; -	u32 tempval; - -	regs = priv->gfargrp[0].regs; -	local_irq_save(flags); -	lock_rx_qs(priv); - -	if (features & NETIF_F_HW_VLAN_CTAG_TX) { -		/* Enable VLAN tag insertion */ -		tempval = gfar_read(®s->tctrl); -		tempval |= TCTRL_VLINS; -		gfar_write(®s->tctrl, tempval); -	} else { -		/* Disable VLAN tag insertion */ -		tempval = gfar_read(®s->tctrl); -		tempval &= ~TCTRL_VLINS; -		gfar_write(®s->tctrl, tempval); -	} - -	if (features & NETIF_F_HW_VLAN_CTAG_RX) { -		/* Enable VLAN tag extraction */ -		tempval = gfar_read(®s->rctrl); -		tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT); -		gfar_write(®s->rctrl, tempval); -		priv->uses_rxfcb = 1; -	} else { -		/* Disable VLAN tag extraction */ -		tempval = gfar_read(®s->rctrl); -		tempval &= ~RCTRL_VLEX; -		gfar_write(®s->rctrl, tempval); - -		gfar_check_rx_parser_mode(priv); -	} - -	gfar_change_mtu(dev, dev->mtu); - -	unlock_rx_qs(priv); -	local_irq_restore(flags); -} -  static int gfar_change_mtu(struct net_device *dev, int new_mtu)  { -	int tempsize, tempval;  	struct gfar_private *priv = netdev_priv(dev); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	int oldsize = priv->rx_buffer_size;  	int frame_size = new_mtu + ETH_HLEN;  	if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { @@ -2418,45 +2440,33 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)  		return -EINVAL;  	} -	if (priv->uses_rxfcb) -		frame_size += GMAC_FCB_LEN; - -	frame_size += priv->padding; - -	tempsize = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) + -		   INCREMENTAL_BUFFER_SIZE; +	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) +		cpu_relax(); -	/* Only stop and start the controller if it isn't already -	 * stopped, and we changed something -	 */ -	if ((oldsize != tempsize) && (dev->flags & IFF_UP)) +	if (dev->flags & IFF_UP)  		stop_gfar(dev); -	priv->rx_buffer_size = tempsize; -  	dev->mtu = new_mtu; -	gfar_write(®s->mrblr, priv->rx_buffer_size); -	gfar_write(®s->maxfrm, priv->rx_buffer_size); +	if (dev->flags & IFF_UP) +		startup_gfar(dev); -	/* If the mtu is larger than the max size for standard -	 * ethernet frames (ie, a jumbo frame), then set maccfg2 -	 * to allow huge frames, and to check the length -	 */ -	tempval = gfar_read(®s->maccfg2); +	clear_bit_unlock(GFAR_RESETTING, &priv->state); -	if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE || -	    gfar_has_errata(priv, GFAR_ERRATA_74)) -		tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); -	else -		tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK); +	return 0; +} -	gfar_write(®s->maccfg2, tempval); +void reset_gfar(struct net_device *ndev) +{ +	struct gfar_private *priv = netdev_priv(ndev); -	if ((oldsize != tempsize) && (dev->flags & IFF_UP)) -		startup_gfar(dev); +	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) +		cpu_relax(); -	return 0; +	stop_gfar(ndev); +	startup_gfar(ndev); + +	clear_bit_unlock(GFAR_RESETTING, &priv->state);  }  /* gfar_reset_task gets scheduled when a packet has not been @@ -2468,16 +2478,7 @@ static void gfar_reset_task(struct work_struct *work)  {  	struct gfar_private *priv = container_of(work, struct gfar_private,  						 reset_task); -	struct net_device *dev = priv->ndev; - -	if (dev->flags & IFF_UP) { -		netif_tx_stop_all_queues(dev); -		stop_gfar(dev); -		startup_gfar(dev); -		netif_tx_start_all_queues(dev); -	} - -	netif_tx_schedule_all(dev); +	reset_gfar(priv->ndev);  }  static void gfar_timeout(struct net_device *dev) @@ -2590,8 +2591,10 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)  	}  	/* If we freed a buffer, we can restart transmission, if necessary */ -	if (netif_tx_queue_stopped(txq) && tx_queue->num_txbdfree) -		netif_wake_subqueue(dev, tqi); +	if (tx_queue->num_txbdfree && +	    netif_tx_queue_stopped(txq) && +	    !(test_bit(GFAR_DOWN, &priv->state))) +		netif_wake_subqueue(priv->ndev, tqi);  	/* Update dirty indicators */  	tx_queue->skb_dirtytx = skb_dirtytx; @@ -2600,31 +2603,6 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)  	netdev_tx_completed_queue(txq, howmany, bytes_sent);  } -static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp) -{ -	unsigned long flags; - -	spin_lock_irqsave(&gfargrp->grplock, flags); -	if (napi_schedule_prep(&gfargrp->napi)) { -		gfar_write(&gfargrp->regs->imask, IMASK_RTX_DISABLED); -		__napi_schedule(&gfargrp->napi); -	} else { -		/* Clear IEVENT, so interrupts aren't called again -		 * because of the packets that have already arrived. -		 */ -		gfar_write(&gfargrp->regs->ievent, IEVENT_RTX_MASK); -	} -	spin_unlock_irqrestore(&gfargrp->grplock, flags); - -} - -/* Interrupt Handler for Transmit complete */ -static irqreturn_t gfar_transmit(int irq, void *grp_id) -{ -	gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); -	return IRQ_HANDLED; -} -  static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,  			   struct sk_buff *skb)  { @@ -2695,7 +2673,48 @@ static inline void count_errors(unsigned short status, struct net_device *dev)  irqreturn_t gfar_receive(int irq, void *grp_id)  { -	gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); +	struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id; +	unsigned long flags; +	u32 imask; + +	if (likely(napi_schedule_prep(&grp->napi_rx))) { +		spin_lock_irqsave(&grp->grplock, flags); +		imask = gfar_read(&grp->regs->imask); +		imask &= IMASK_RX_DISABLED; +		gfar_write(&grp->regs->imask, imask); +		spin_unlock_irqrestore(&grp->grplock, flags); +		__napi_schedule(&grp->napi_rx); +	} else { +		/* Clear IEVENT, so interrupts aren't called again +		 * because of the packets that have already arrived. +		 */ +		gfar_write(&grp->regs->ievent, IEVENT_RX_MASK); +	} + +	return IRQ_HANDLED; +} + +/* Interrupt Handler for Transmit complete */ +static irqreturn_t gfar_transmit(int irq, void *grp_id) +{ +	struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id; +	unsigned long flags; +	u32 imask; + +	if (likely(napi_schedule_prep(&grp->napi_tx))) { +		spin_lock_irqsave(&grp->grplock, flags); +		imask = gfar_read(&grp->regs->imask); +		imask &= IMASK_TX_DISABLED; +		gfar_write(&grp->regs->imask, imask); +		spin_unlock_irqrestore(&grp->grplock, flags); +		__napi_schedule(&grp->napi_tx); +	} else { +		/* Clear IEVENT, so interrupts aren't called again +		 * because of the packets that have already arrived. +		 */ +		gfar_write(&grp->regs->ievent, IEVENT_TX_MASK); +	} +  	return IRQ_HANDLED;  } @@ -2819,7 +2838,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)  				rx_queue->stats.rx_bytes += pkt_len;  				skb_record_rx_queue(skb, rx_queue->qindex);  				gfar_process_frame(dev, skb, amount_pull, -						   &rx_queue->grp->napi); +						   &rx_queue->grp->napi_rx);  			} else {  				netif_warn(priv, rx_err, dev, "Missing skb!\n"); @@ -2848,66 +2867,81 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)  	return howmany;  } -static int gfar_poll_sq(struct napi_struct *napi, int budget) +static int gfar_poll_rx_sq(struct napi_struct *napi, int budget)  {  	struct gfar_priv_grp *gfargrp = -		container_of(napi, struct gfar_priv_grp, napi); +		container_of(napi, struct gfar_priv_grp, napi_rx);  	struct gfar __iomem *regs = gfargrp->regs; -	struct gfar_priv_tx_q *tx_queue = gfargrp->priv->tx_queue[0]; -	struct gfar_priv_rx_q *rx_queue = gfargrp->priv->rx_queue[0]; +	struct gfar_priv_rx_q *rx_queue = gfargrp->rx_queue;  	int work_done = 0;  	/* Clear IEVENT, so interrupts aren't called again  	 * because of the packets that have already arrived  	 */ -	gfar_write(®s->ievent, IEVENT_RTX_MASK); - -	/* run Tx cleanup to completion */ -	if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) -		gfar_clean_tx_ring(tx_queue); +	gfar_write(®s->ievent, IEVENT_RX_MASK);  	work_done = gfar_clean_rx_ring(rx_queue, budget);  	if (work_done < budget) { +		u32 imask;  		napi_complete(napi);  		/* Clear the halt bit in RSTAT */  		gfar_write(®s->rstat, gfargrp->rstat); -		gfar_write(®s->imask, IMASK_DEFAULT); - -		/* If we are coalescing interrupts, update the timer -		 * Otherwise, clear it -		 */ -		gfar_write(®s->txic, 0); -		if (likely(tx_queue->txcoalescing)) -			gfar_write(®s->txic, tx_queue->txic); - -		gfar_write(®s->rxic, 0); -		if (unlikely(rx_queue->rxcoalescing)) -			gfar_write(®s->rxic, rx_queue->rxic); +		spin_lock_irq(&gfargrp->grplock); +		imask = gfar_read(®s->imask); +		imask |= IMASK_RX_DEFAULT; +		gfar_write(®s->imask, imask); +		spin_unlock_irq(&gfargrp->grplock);  	}  	return work_done;  } -static int gfar_poll(struct napi_struct *napi, int budget) +static int gfar_poll_tx_sq(struct napi_struct *napi, int budget) +{ +	struct gfar_priv_grp *gfargrp = +		container_of(napi, struct gfar_priv_grp, napi_tx); +	struct gfar __iomem *regs = gfargrp->regs; +	struct gfar_priv_tx_q *tx_queue = gfargrp->tx_queue; +	u32 imask; + +	/* Clear IEVENT, so interrupts aren't called again +	 * because of the packets that have already arrived +	 */ +	gfar_write(®s->ievent, IEVENT_TX_MASK); + +	/* run Tx cleanup to completion */ +	if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) +		gfar_clean_tx_ring(tx_queue); + +	napi_complete(napi); + +	spin_lock_irq(&gfargrp->grplock); +	imask = gfar_read(®s->imask); +	imask |= IMASK_TX_DEFAULT; +	gfar_write(®s->imask, imask); +	spin_unlock_irq(&gfargrp->grplock); + +	return 0; +} + +static int gfar_poll_rx(struct napi_struct *napi, int budget)  {  	struct gfar_priv_grp *gfargrp = -		container_of(napi, struct gfar_priv_grp, napi); +		container_of(napi, struct gfar_priv_grp, napi_rx);  	struct gfar_private *priv = gfargrp->priv;  	struct gfar __iomem *regs = gfargrp->regs; -	struct gfar_priv_tx_q *tx_queue = NULL;  	struct gfar_priv_rx_q *rx_queue = NULL;  	int work_done = 0, work_done_per_q = 0;  	int i, budget_per_q = 0; -	int has_tx_work;  	unsigned long rstat_rxf;  	int num_act_queues;  	/* Clear IEVENT, so interrupts aren't called again  	 * because of the packets that have already arrived  	 */ -	gfar_write(®s->ievent, IEVENT_RTX_MASK); +	gfar_write(®s->ievent, IEVENT_RX_MASK);  	rstat_rxf = gfar_read(®s->rstat) & RSTAT_RXF_MASK; @@ -2915,67 +2949,84 @@ static int gfar_poll(struct napi_struct *napi, int budget)  	if (num_act_queues)  		budget_per_q = budget/num_act_queues; -	while (1) { -		has_tx_work = 0; -		for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) { -			tx_queue = priv->tx_queue[i]; -			/* run Tx cleanup to completion */ -			if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) { -				gfar_clean_tx_ring(tx_queue); -				has_tx_work = 1; -			} -		} +	for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { +		/* skip queue if not active */ +		if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i))) +			continue; -		for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { -			/* skip queue if not active */ -			if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i))) -				continue; - -			rx_queue = priv->rx_queue[i]; -			work_done_per_q = -				gfar_clean_rx_ring(rx_queue, budget_per_q); -			work_done += work_done_per_q; - -			/* finished processing this queue */ -			if (work_done_per_q < budget_per_q) { -				/* clear active queue hw indication */ -				gfar_write(®s->rstat, -					   RSTAT_CLEAR_RXF0 >> i); -				rstat_rxf &= ~(RSTAT_CLEAR_RXF0 >> i); -				num_act_queues--; - -				if (!num_act_queues) -					break; -				/* recompute budget per Rx queue */ -				budget_per_q = -					(budget - work_done) / num_act_queues; -			} +		rx_queue = priv->rx_queue[i]; +		work_done_per_q = +			gfar_clean_rx_ring(rx_queue, budget_per_q); +		work_done += work_done_per_q; + +		/* finished processing this queue */ +		if (work_done_per_q < budget_per_q) { +			/* clear active queue hw indication */ +			gfar_write(®s->rstat, +				   RSTAT_CLEAR_RXF0 >> i); +			num_act_queues--; + +			if (!num_act_queues) +				break;  		} +	} -		if (work_done >= budget) -			break; +	if (!num_act_queues) { +		u32 imask; +		napi_complete(napi); -		if (!num_act_queues && !has_tx_work) { +		/* Clear the halt bit in RSTAT */ +		gfar_write(®s->rstat, gfargrp->rstat); -			napi_complete(napi); +		spin_lock_irq(&gfargrp->grplock); +		imask = gfar_read(®s->imask); +		imask |= IMASK_RX_DEFAULT; +		gfar_write(®s->imask, imask); +		spin_unlock_irq(&gfargrp->grplock); +	} -			/* Clear the halt bit in RSTAT */ -			gfar_write(®s->rstat, gfargrp->rstat); +	return work_done; +} -			gfar_write(®s->imask, IMASK_DEFAULT); +static int gfar_poll_tx(struct napi_struct *napi, int budget) +{ +	struct gfar_priv_grp *gfargrp = +		container_of(napi, struct gfar_priv_grp, napi_tx); +	struct gfar_private *priv = gfargrp->priv; +	struct gfar __iomem *regs = gfargrp->regs; +	struct gfar_priv_tx_q *tx_queue = NULL; +	int has_tx_work = 0; +	int i; -			/* If we are coalescing interrupts, update the timer -			 * Otherwise, clear it -			 */ -			gfar_configure_coalescing(priv, gfargrp->rx_bit_map, -						  gfargrp->tx_bit_map); -			break; +	/* Clear IEVENT, so interrupts aren't called again +	 * because of the packets that have already arrived +	 */ +	gfar_write(®s->ievent, IEVENT_TX_MASK); + +	for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) { +		tx_queue = priv->tx_queue[i]; +		/* run Tx cleanup to completion */ +		if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) { +			gfar_clean_tx_ring(tx_queue); +			has_tx_work = 1;  		}  	} -	return work_done; +	if (!has_tx_work) { +		u32 imask; +		napi_complete(napi); + +		spin_lock_irq(&gfargrp->grplock); +		imask = gfar_read(®s->imask); +		imask |= IMASK_TX_DEFAULT; +		gfar_write(®s->imask, imask); +		spin_unlock_irq(&gfargrp->grplock); +	} + +	return 0;  } +  #ifdef CONFIG_NET_POLL_CONTROLLER  /* Polling 'interrupt' - used by things like netconsole to send skbs   * without having to re-enable interrupts. It's not called while @@ -3034,41 +3085,6 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id)  	return IRQ_HANDLED;  } -static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) -{ -	struct phy_device *phydev = priv->phydev; -	u32 val = 0; - -	if (!phydev->duplex) -		return val; - -	if (!priv->pause_aneg_en) { -		if (priv->tx_pause_en) -			val |= MACCFG1_TX_FLOW; -		if (priv->rx_pause_en) -			val |= MACCFG1_RX_FLOW; -	} else { -		u16 lcl_adv, rmt_adv; -		u8 flowctrl; -		/* get link partner capabilities */ -		rmt_adv = 0; -		if (phydev->pause) -			rmt_adv = LPA_PAUSE_CAP; -		if (phydev->asym_pause) -			rmt_adv |= LPA_PAUSE_ASYM; - -		lcl_adv = mii_advertise_flowctrl(phydev->advertising); - -		flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); -		if (flowctrl & FLOW_CTRL_TX) -			val |= MACCFG1_TX_FLOW; -		if (flowctrl & FLOW_CTRL_RX) -			val |= MACCFG1_RX_FLOW; -	} - -	return val; -} -  /* Called every time the controller might need to be made   * aware of new link state.  The PHY code conveys this   * information through variables in the phydev structure, and this @@ -3078,86 +3094,12 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)  static void adjust_link(struct net_device *dev)  {  	struct gfar_private *priv = netdev_priv(dev); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	unsigned long flags;  	struct phy_device *phydev = priv->phydev; -	int new_state = 0; - -	local_irq_save(flags); -	lock_tx_qs(priv); - -	if (phydev->link) { -		u32 tempval1 = gfar_read(®s->maccfg1); -		u32 tempval = gfar_read(®s->maccfg2); -		u32 ecntrl = gfar_read(®s->ecntrl); - -		/* Now we make sure that we can be in full duplex mode. -		 * If not, we operate in half-duplex mode. -		 */ -		if (phydev->duplex != priv->oldduplex) { -			new_state = 1; -			if (!(phydev->duplex)) -				tempval &= ~(MACCFG2_FULL_DUPLEX); -			else -				tempval |= MACCFG2_FULL_DUPLEX; - -			priv->oldduplex = phydev->duplex; -		} - -		if (phydev->speed != priv->oldspeed) { -			new_state = 1; -			switch (phydev->speed) { -			case 1000: -				tempval = -				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); - -				ecntrl &= ~(ECNTRL_R100); -				break; -			case 100: -			case 10: -				tempval = -				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); - -				/* Reduced mode distinguishes -				 * between 10 and 100 -				 */ -				if (phydev->speed == SPEED_100) -					ecntrl |= ECNTRL_R100; -				else -					ecntrl &= ~(ECNTRL_R100); -				break; -			default: -				netif_warn(priv, link, dev, -					   "Ack!  Speed (%d) is not 10/100/1000!\n", -					   phydev->speed); -				break; -			} - -			priv->oldspeed = phydev->speed; -		} - -		tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); -		tempval1 |= gfar_get_flowctrl_cfg(priv); - -		gfar_write(®s->maccfg1, tempval1); -		gfar_write(®s->maccfg2, tempval); -		gfar_write(®s->ecntrl, ecntrl); - -		if (!priv->oldlink) { -			new_state = 1; -			priv->oldlink = 1; -		} -	} else if (priv->oldlink) { -		new_state = 1; -		priv->oldlink = 0; -		priv->oldspeed = 0; -		priv->oldduplex = -1; -	} -	if (new_state && netif_msg_link(priv)) -		phy_print_status(phydev); -	unlock_tx_qs(priv); -	local_irq_restore(flags); +	if (unlikely(phydev->link != priv->oldlink || +		     phydev->duplex != priv->oldduplex || +		     phydev->speed != priv->oldspeed)) +		gfar_update_link_state(priv);  }  /* Update the hash table based on the current list of multicast @@ -3403,6 +3345,114 @@ static irqreturn_t gfar_error(int irq, void *grp_id)  	return IRQ_HANDLED;  } +static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) +{ +	struct phy_device *phydev = priv->phydev; +	u32 val = 0; + +	if (!phydev->duplex) +		return val; + +	if (!priv->pause_aneg_en) { +		if (priv->tx_pause_en) +			val |= MACCFG1_TX_FLOW; +		if (priv->rx_pause_en) +			val |= MACCFG1_RX_FLOW; +	} else { +		u16 lcl_adv, rmt_adv; +		u8 flowctrl; +		/* get link partner capabilities */ +		rmt_adv = 0; +		if (phydev->pause) +			rmt_adv = LPA_PAUSE_CAP; +		if (phydev->asym_pause) +			rmt_adv |= LPA_PAUSE_ASYM; + +		lcl_adv = mii_advertise_flowctrl(phydev->advertising); + +		flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); +		if (flowctrl & FLOW_CTRL_TX) +			val |= MACCFG1_TX_FLOW; +		if (flowctrl & FLOW_CTRL_RX) +			val |= MACCFG1_RX_FLOW; +	} + +	return val; +} + +static noinline void gfar_update_link_state(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	struct phy_device *phydev = priv->phydev; + +	if (unlikely(test_bit(GFAR_RESETTING, &priv->state))) +		return; + +	if (phydev->link) { +		u32 tempval1 = gfar_read(®s->maccfg1); +		u32 tempval = gfar_read(®s->maccfg2); +		u32 ecntrl = gfar_read(®s->ecntrl); + +		if (phydev->duplex != priv->oldduplex) { +			if (!(phydev->duplex)) +				tempval &= ~(MACCFG2_FULL_DUPLEX); +			else +				tempval |= MACCFG2_FULL_DUPLEX; + +			priv->oldduplex = phydev->duplex; +		} + +		if (phydev->speed != priv->oldspeed) { +			switch (phydev->speed) { +			case 1000: +				tempval = +				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); + +				ecntrl &= ~(ECNTRL_R100); +				break; +			case 100: +			case 10: +				tempval = +				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); + +				/* Reduced mode distinguishes +				 * between 10 and 100 +				 */ +				if (phydev->speed == SPEED_100) +					ecntrl |= ECNTRL_R100; +				else +					ecntrl &= ~(ECNTRL_R100); +				break; +			default: +				netif_warn(priv, link, priv->ndev, +					   "Ack!  Speed (%d) is not 10/100/1000!\n", +					   phydev->speed); +				break; +			} + +			priv->oldspeed = phydev->speed; +		} + +		tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); +		tempval1 |= gfar_get_flowctrl_cfg(priv); + +		gfar_write(®s->maccfg1, tempval1); +		gfar_write(®s->maccfg2, tempval); +		gfar_write(®s->ecntrl, ecntrl); + +		if (!priv->oldlink) +			priv->oldlink = 1; + +	} else if (priv->oldlink) { +		priv->oldlink = 0; +		priv->oldspeed = 0; +		priv->oldduplex = -1; +	} + +	if (netif_msg_link(priv)) +		phy_print_status(phydev); +} +  static struct of_device_id gfar_match[] =  {  	{ diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 04112b98ff5..84632c569f2 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -9,7 +9,7 @@   * Maintainer: Kumar Gala   * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>   * - * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc. + * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.   *   * This program is free software; you can redistribute  it and/or modify it   * under  the terms of  the GNU General  Public License as published by the @@ -29,7 +29,6 @@  #include <linux/errno.h>  #include <linux/slab.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -378,8 +377,11 @@ extern const char gfar_driver_version[];  		IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \  		IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \  		| IMASK_PERR) -#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \ -			   & IMASK_DEFAULT) +#define IMASK_RX_DEFAULT (IMASK_RXFEN0 | IMASK_BSY) +#define IMASK_TX_DEFAULT (IMASK_TXFEN | IMASK_TXBEN) + +#define IMASK_RX_DISABLED ((~(IMASK_RX_DEFAULT)) & IMASK_DEFAULT) +#define IMASK_TX_DISABLED ((~(IMASK_TX_DEFAULT)) & IMASK_DEFAULT)  /* Fifo management */  #define FIFO_TX_THR_MASK	0x01ff @@ -410,7 +412,9 @@ extern const char gfar_driver_version[];  /* This default RIR value directly corresponds   * to the 3-bit hash value generated */ -#define DEFAULT_RIR0	0x05397700 +#define DEFAULT_8RXQ_RIR0	0x05397700 +/* Map even hash values to Q0, and odd ones to Q1 */ +#define DEFAULT_2RXQ_RIR0	0x04104100  /* RQFCR register bits */  #define RQFCR_GPI		0x80000000 @@ -881,7 +885,6 @@ struct gfar {  #define FSL_GIANFAR_DEV_HAS_CSUM		0x00000010  #define FSL_GIANFAR_DEV_HAS_VLAN		0x00000020  #define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH	0x00000040 -#define FSL_GIANFAR_DEV_HAS_PADDING		0x00000080  #define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET	0x00000100  #define FSL_GIANFAR_DEV_HAS_BD_STASHING		0x00000200  #define FSL_GIANFAR_DEV_HAS_BUF_STASHING	0x00000400 @@ -893,8 +896,8 @@ struct gfar {  #define DEFAULT_MAPPING 	0xFF  #endif -#define ISRG_SHIFT_TX	0x10 -#define ISRG_SHIFT_RX	0x18 +#define ISRG_RR0	0x80000000 +#define ISRG_TR0	0x00800000  /* The same driver can operate in two modes */  /* SQ_SG_MODE: Single Queue Single Group Mode @@ -906,6 +909,22 @@ enum {  	MQ_MG_MODE  }; +/* GFAR_SQ_POLLING: Single Queue NAPI polling mode + *	The driver supports a single pair of RX/Tx queues + *	per interrupt group (Rx/Tx int line). MQ_MG mode + *	devices have 2 interrupt groups, so the device will + *	have a total of 2 Tx and 2 Rx queues in this case. + * GFAR_MQ_POLLING: Multi Queue NAPI polling mode + *	The driver supports all the 8 Rx and Tx HW queues + *	each queue mapped by the Device Tree to one of + *	the 2 interrupt groups. This mode implies significant + *	processing overhead (CPU and controller level). + */ +enum gfar_poll_mode { +	GFAR_SQ_POLLING = 0, +	GFAR_MQ_POLLING +}; +  /*   * Per TX queue stats   */ @@ -967,7 +986,6 @@ struct rx_q_stats {  /**   *	struct gfar_priv_rx_q - per rx queue structure - *	@rxlock: per queue rx spin lock   *	@rx_skbuff: skb pointers   *	@skb_currx: currently use skb pointer   *	@rx_bd_base: First rx buffer descriptor @@ -980,8 +998,7 @@ struct rx_q_stats {   */  struct gfar_priv_rx_q { -	spinlock_t rxlock __attribute__ ((aligned (SMP_CACHE_BYTES))); -	struct	sk_buff ** rx_skbuff; +	struct	sk_buff **rx_skbuff __aligned(SMP_CACHE_BYTES);  	dma_addr_t rx_bd_dma_base;  	struct	rxbd8 *rx_bd_base;  	struct	rxbd8 *cur_rx; @@ -1017,17 +1034,20 @@ struct gfar_irqinfo {   */  struct gfar_priv_grp { -	spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES))); -	struct	napi_struct napi; -	struct gfar_private *priv; +	spinlock_t grplock __aligned(SMP_CACHE_BYTES); +	struct	napi_struct napi_rx; +	struct	napi_struct napi_tx;  	struct gfar __iomem *regs; -	unsigned int rstat; -	unsigned long num_rx_queues; -	unsigned long rx_bit_map; -	/* cacheline 3 */ +	struct gfar_priv_tx_q *tx_queue; +	struct gfar_priv_rx_q *rx_queue;  	unsigned int tstat; +	unsigned int rstat; + +	struct gfar_private *priv;  	unsigned long num_tx_queues;  	unsigned long tx_bit_map; +	unsigned long num_rx_queues; +	unsigned long rx_bit_map;  	struct gfar_irqinfo *irqinfo[GFAR_NUM_IRQS];  }; @@ -1042,6 +1062,11 @@ enum gfar_errata {  	GFAR_ERRATA_12		= 0x08, /* a.k.a errata eTSEC49 */  }; +enum gfar_dev_state { +	GFAR_DOWN = 1, +	GFAR_RESETTING +}; +  /* Struct stolen almost completely (and shamelessly) from the FCC enet source   * (Ok, that's not so true anymore, but there is a family resemblance)   * The GFAR buffer descriptors track the ring buffers.  The rx_bd_base @@ -1052,8 +1077,6 @@ enum gfar_errata {   * the buffer descriptor determines the actual condition.   */  struct gfar_private { -	unsigned int num_rx_queues; -  	struct device *dev;  	struct net_device *ndev;  	enum gfar_errata errata; @@ -1061,6 +1084,7 @@ struct gfar_private {  	u16 uses_rxfcb;  	u16 padding; +	u32 device_flags;  	/* HW time stamping enabled flag */  	int hwts_rx_en; @@ -1070,10 +1094,12 @@ struct gfar_private {  	struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];  	struct gfar_priv_grp gfargrp[MAXGROUPS]; -	u32 device_flags; +	unsigned long state; -	unsigned int mode; +	unsigned short mode; +	unsigned short poll_mode;  	unsigned int num_tx_queues; +	unsigned int num_rx_queues;  	unsigned int num_grps;  	/* Network Statistics */ @@ -1114,6 +1140,9 @@ struct gfar_private {  	unsigned int total_tx_ring_size;  	unsigned int total_rx_ring_size; +	u32 rqueue; +	u32 tqueue; +  	/* RX per device parameters */  	unsigned int rx_stash_size;  	unsigned int rx_stash_index; @@ -1128,11 +1157,6 @@ struct gfar_private {  	u32 __iomem *hash_regs[16];  	int hash_width; -	/* global parameters */ -	unsigned int fifo_threshold; -	unsigned int fifo_starve; -	unsigned int fifo_starve_off; -  	/*Filer table*/  	unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];  	unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; @@ -1177,21 +1201,42 @@ static inline void gfar_read_filer(struct gfar_private *priv,  	*fpr = gfar_read(®s->rqfpr);  } -extern void lock_rx_qs(struct gfar_private *priv); -extern void lock_tx_qs(struct gfar_private *priv); -extern void unlock_rx_qs(struct gfar_private *priv); -extern void unlock_tx_qs(struct gfar_private *priv); -extern irqreturn_t gfar_receive(int irq, void *dev_id); -extern int startup_gfar(struct net_device *dev); -extern void stop_gfar(struct net_device *dev); -extern void gfar_halt(struct net_device *dev); -extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, -		int enable, u32 regnum, u32 read); -extern void gfar_configure_coalescing_all(struct gfar_private *priv); -void gfar_init_sysfs(struct net_device *dev); +static inline void gfar_write_isrg(struct gfar_private *priv) +{ +	struct gfar __iomem *regs = priv->gfargrp[0].regs; +	u32 __iomem *baddr = ®s->isrg0; +	u32 isrg = 0; +	int grp_idx, i; + +	for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) { +		struct gfar_priv_grp *grp = &priv->gfargrp[grp_idx]; + +		for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) { +			isrg |= (ISRG_RR0 >> i); +		} + +		for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) { +			isrg |= (ISRG_TR0 >> i); +		} + +		gfar_write(baddr, isrg); + +		baddr++; +		isrg = 0; +	} +} + +irqreturn_t gfar_receive(int irq, void *dev_id); +int startup_gfar(struct net_device *dev); +void stop_gfar(struct net_device *dev); +void reset_gfar(struct net_device *dev); +void gfar_mac_reset(struct gfar_private *priv); +void gfar_halt(struct gfar_private *priv); +void gfar_start(struct gfar_private *priv); +void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable, +		   u32 regnum, u32 read); +void gfar_configure_coalescing_all(struct gfar_private *priv);  int gfar_set_features(struct net_device *dev, netdev_features_t features); -extern void gfar_check_rx_parser_mode(struct gfar_private *priv); -extern void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);  extern const struct ethtool_ops gfar_ethtool_ops; diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index d3d7ede27ef..76d70708f86 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -22,7 +22,6 @@  #include <linux/string.h>  #include <linux/errno.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/delay.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -45,10 +44,6 @@  #include "gianfar.h" -extern void gfar_start(struct net_device *dev); -extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, -			      int rx_work_limit); -  #define GFAR_MAX_COAL_USECS 0xffff  #define GFAR_MAX_COAL_FRAMES 0xff  static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, @@ -365,25 +360,11 @@ static int gfar_scoalesce(struct net_device *dev,  			  struct ethtool_coalesce *cvals)  {  	struct gfar_private *priv = netdev_priv(dev); -	int i = 0; +	int i, err = 0;  	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))  		return -EOPNOTSUPP; -	/* Set up rx coalescing */ -	/* As of now, we will enable/disable coalescing for all -	 * queues together in case of eTSEC2, this will be modified -	 * along with the ethtool interface -	 */ -	if ((cvals->rx_coalesce_usecs == 0) || -	    (cvals->rx_max_coalesced_frames == 0)) { -		for (i = 0; i < priv->num_rx_queues; i++) -			priv->rx_queue[i]->rxcoalescing = 0; -	} else { -		for (i = 0; i < priv->num_rx_queues; i++) -			priv->rx_queue[i]->rxcoalescing = 1; -	} -  	if (NULL == priv->phydev)  		return -ENODEV; @@ -400,6 +381,32 @@ static int gfar_scoalesce(struct net_device *dev,  		return -EINVAL;  	} +	/* Check the bounds of the values */ +	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { +		netdev_info(dev, "Coalescing is limited to %d microseconds\n", +			    GFAR_MAX_COAL_USECS); +		return -EINVAL; +	} + +	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { +		netdev_info(dev, "Coalescing is limited to %d frames\n", +			    GFAR_MAX_COAL_FRAMES); +		return -EINVAL; +	} + +	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) +		cpu_relax(); + +	/* Set up rx coalescing */ +	if ((cvals->rx_coalesce_usecs == 0) || +	    (cvals->rx_max_coalesced_frames == 0)) { +		for (i = 0; i < priv->num_rx_queues; i++) +			priv->rx_queue[i]->rxcoalescing = 0; +	} else { +		for (i = 0; i < priv->num_rx_queues; i++) +			priv->rx_queue[i]->rxcoalescing = 1; +	} +  	for (i = 0; i < priv->num_rx_queues; i++) {  		priv->rx_queue[i]->rxic = mk_ic_value(  			cvals->rx_max_coalesced_frames, @@ -416,28 +423,22 @@ static int gfar_scoalesce(struct net_device *dev,  			priv->tx_queue[i]->txcoalescing = 1;  	} -	/* Check the bounds of the values */ -	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { -		netdev_info(dev, "Coalescing is limited to %d microseconds\n", -			    GFAR_MAX_COAL_USECS); -		return -EINVAL; -	} - -	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { -		netdev_info(dev, "Coalescing is limited to %d frames\n", -			    GFAR_MAX_COAL_FRAMES); -		return -EINVAL; -	} -  	for (i = 0; i < priv->num_tx_queues; i++) {  		priv->tx_queue[i]->txic = mk_ic_value(  			cvals->tx_max_coalesced_frames,  			gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));  	} -	gfar_configure_coalescing_all(priv); +	if (dev->flags & IFF_UP) { +		stop_gfar(dev); +		err = startup_gfar(dev); +	} else { +		gfar_mac_reset(priv); +	} + +	clear_bit_unlock(GFAR_RESETTING, &priv->state); -	return 0; +	return err;  }  /* Fills in rvals with the current ring parameters.  Currently, @@ -468,15 +469,13 @@ static void gfar_gringparam(struct net_device *dev,  }  /* Change the current ring parameters, stopping the controller if - * necessary so that we don't mess things up while we're in - * motion.  We wait for the ring to be clean before reallocating - * the rings. + * necessary so that we don't mess things up while we're in motion.   */  static int gfar_sringparam(struct net_device *dev,  			   struct ethtool_ringparam *rvals)  {  	struct gfar_private *priv = netdev_priv(dev); -	int err = 0, i = 0; +	int err = 0, i;  	if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)  		return -EINVAL; @@ -494,44 +493,25 @@ static int gfar_sringparam(struct net_device *dev,  		return -EINVAL;  	} +	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) +		cpu_relax(); -	if (dev->flags & IFF_UP) { -		unsigned long flags; - -		/* Halt TX and RX, and process the frames which -		 * have already been received -		 */ -		local_irq_save(flags); -		lock_tx_qs(priv); -		lock_rx_qs(priv); - -		gfar_halt(dev); - -		unlock_rx_qs(priv); -		unlock_tx_qs(priv); -		local_irq_restore(flags); - -		for (i = 0; i < priv->num_rx_queues; i++) -			gfar_clean_rx_ring(priv->rx_queue[i], -					   priv->rx_queue[i]->rx_ring_size); - -		/* Now we take down the rings to rebuild them */ +	if (dev->flags & IFF_UP)  		stop_gfar(dev); -	} -	/* Change the size */ -	for (i = 0; i < priv->num_rx_queues; i++) { +	/* Change the sizes */ +	for (i = 0; i < priv->num_rx_queues; i++)  		priv->rx_queue[i]->rx_ring_size = rvals->rx_pending; + +	for (i = 0; i < priv->num_tx_queues; i++)  		priv->tx_queue[i]->tx_ring_size = rvals->tx_pending; -		priv->tx_queue[i]->num_txbdfree = -			priv->tx_queue[i]->tx_ring_size; -	}  	/* Rebuild the rings with the new size */ -	if (dev->flags & IFF_UP) { +	if (dev->flags & IFF_UP)  		err = startup_gfar(dev); -		netif_tx_wake_all_queues(dev); -	} + +	clear_bit_unlock(GFAR_RESETTING, &priv->state); +  	return err;  } @@ -553,6 +533,9 @@ static int gfar_spauseparam(struct net_device *dev,  	struct gfar __iomem *regs = priv->gfargrp[0].regs;  	u32 oldadv, newadv; +	if (!phydev) +		return -ENODEV; +  	if (!(phydev->supported & SUPPORTED_Pause) ||  	    (!(phydev->supported & SUPPORTED_Asym_Pause) &&  	     (epause->rx_pause != epause->tx_pause))) @@ -609,43 +592,29 @@ static int gfar_spauseparam(struct net_device *dev,  int gfar_set_features(struct net_device *dev, netdev_features_t features)  { -	struct gfar_private *priv = netdev_priv(dev); -	unsigned long flags; -	int err = 0, i = 0;  	netdev_features_t changed = dev->features ^ features; +	struct gfar_private *priv = netdev_priv(dev); +	int err = 0; -	if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX)) -		gfar_vlan_mode(dev, features); - -	if (!(changed & NETIF_F_RXCSUM)) +	if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | +			 NETIF_F_RXCSUM)))  		return 0; -	if (dev->flags & IFF_UP) { -		/* Halt TX and RX, and process the frames which -		 * have already been received -		 */ -		local_irq_save(flags); -		lock_tx_qs(priv); -		lock_rx_qs(priv); +	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) +		cpu_relax(); -		gfar_halt(dev); - -		unlock_tx_qs(priv); -		unlock_rx_qs(priv); -		local_irq_restore(flags); - -		for (i = 0; i < priv->num_rx_queues; i++) -			gfar_clean_rx_ring(priv->rx_queue[i], -					   priv->rx_queue[i]->rx_ring_size); +	dev->features = features; +	if (dev->flags & IFF_UP) {  		/* Now we take down the rings to rebuild them */  		stop_gfar(dev); - -		dev->features = features; -  		err = startup_gfar(dev); -		netif_tx_wake_all_queues(dev); +	} else { +		gfar_mac_reset(priv);  	} + +	clear_bit_unlock(GFAR_RESETTING, &priv->state); +  	return err;  } @@ -889,11 +858,9 @@ static int gfar_set_hash_opts(struct gfar_private *priv,  static int gfar_check_filer_hardware(struct gfar_private *priv)  { -	struct gfar __iomem *regs = NULL; +	struct gfar __iomem *regs = priv->gfargrp[0].regs;  	u32 i; -	regs = priv->gfargrp[0].regs; -  	/* Check if we are in FIFO mode */  	i = gfar_read(®s->ecntrl);  	i &= ECNTRL_FIFM; @@ -927,7 +894,7 @@ static int gfar_check_filer_hardware(struct gfar_private *priv)  	/* Sets the properties for arbitrary filer rule  	 * to the first 4 Layer 4 Bytes  	 */ -	regs->rbifx = 0xC0C1C2C3; +	gfar_write(®s->rbifx, 0xC0C1C2C3);  	return 0;  } @@ -1055,10 +1022,18 @@ static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value,  			      struct ethtool_tcpip4_spec *mask,  			      struct filer_table *tab)  { -	gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab); -	gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab); -	gfar_set_attribute(value->pdst, mask->pdst, RQFCR_PID_DPT, tab); -	gfar_set_attribute(value->psrc, mask->psrc, RQFCR_PID_SPT, tab); +	gfar_set_attribute(be32_to_cpu(value->ip4src), +			   be32_to_cpu(mask->ip4src), +			   RQFCR_PID_SIA, tab); +	gfar_set_attribute(be32_to_cpu(value->ip4dst), +			   be32_to_cpu(mask->ip4dst), +			   RQFCR_PID_DIA, tab); +	gfar_set_attribute(be16_to_cpu(value->pdst), +			   be16_to_cpu(mask->pdst), +			   RQFCR_PID_DPT, tab); +	gfar_set_attribute(be16_to_cpu(value->psrc), +			   be16_to_cpu(mask->psrc), +			   RQFCR_PID_SPT, tab);  	gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);  } @@ -1067,12 +1042,17 @@ static void gfar_set_user_ip(struct ethtool_usrip4_spec *value,  			     struct ethtool_usrip4_spec *mask,  			     struct filer_table *tab)  { -	gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab); -	gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab); +	gfar_set_attribute(be32_to_cpu(value->ip4src), +			   be32_to_cpu(mask->ip4src), +			   RQFCR_PID_SIA, tab); +	gfar_set_attribute(be32_to_cpu(value->ip4dst), +			   be32_to_cpu(mask->ip4dst), +			   RQFCR_PID_DIA, tab);  	gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);  	gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab); -	gfar_set_attribute(value->l4_4_bytes, mask->l4_4_bytes, RQFCR_PID_ARB, -			   tab); +	gfar_set_attribute(be32_to_cpu(value->l4_4_bytes), +			   be32_to_cpu(mask->l4_4_bytes), +			   RQFCR_PID_ARB, tab);  } @@ -1139,7 +1119,41 @@ static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask,  		}  	} -	gfar_set_attribute(value->h_proto, mask->h_proto, RQFCR_PID_ETY, tab); +	gfar_set_attribute(be16_to_cpu(value->h_proto), +			   be16_to_cpu(mask->h_proto), +			   RQFCR_PID_ETY, tab); +} + +static inline u32 vlan_tci_vid(struct ethtool_rx_flow_spec *rule) +{ +	return be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_VID_MASK; +} + +static inline u32 vlan_tci_vidm(struct ethtool_rx_flow_spec *rule) +{ +	return be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_VID_MASK; +} + +static inline u32 vlan_tci_cfi(struct ethtool_rx_flow_spec *rule) +{ +	return be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_CFI_MASK; +} + +static inline u32 vlan_tci_cfim(struct ethtool_rx_flow_spec *rule) +{ +	return be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_CFI_MASK; +} + +static inline u32 vlan_tci_prio(struct ethtool_rx_flow_spec *rule) +{ +	return (be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_PRIO_MASK) >> +		VLAN_PRIO_SHIFT; +} + +static inline u32 vlan_tci_priom(struct ethtool_rx_flow_spec *rule) +{ +	return (be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_PRIO_MASK) >> +		VLAN_PRIO_SHIFT;  }  /* Convert a rule to binary filter format of gianfar */ @@ -1153,22 +1167,21 @@ static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,  	u32 old_index = tab->index;  	/* Check if vlan is wanted */ -	if ((rule->flow_type & FLOW_EXT) && (rule->m_ext.vlan_tci != 0xFFFF)) { +	if ((rule->flow_type & FLOW_EXT) && +	    (rule->m_ext.vlan_tci != cpu_to_be16(0xFFFF))) {  		if (!rule->m_ext.vlan_tci) -			rule->m_ext.vlan_tci = 0xFFFF; +			rule->m_ext.vlan_tci = cpu_to_be16(0xFFFF);  		vlan = RQFPR_VLN;  		vlan_mask = RQFPR_VLN;  		/* Separate the fields */ -		id = rule->h_ext.vlan_tci & VLAN_VID_MASK; -		id_mask = rule->m_ext.vlan_tci & VLAN_VID_MASK; -		cfi = rule->h_ext.vlan_tci & VLAN_CFI_MASK; -		cfi_mask = rule->m_ext.vlan_tci & VLAN_CFI_MASK; -		prio = (rule->h_ext.vlan_tci & VLAN_PRIO_MASK) >> -		       VLAN_PRIO_SHIFT; -		prio_mask = (rule->m_ext.vlan_tci & VLAN_PRIO_MASK) >> -			    VLAN_PRIO_SHIFT; +		id = vlan_tci_vid(rule); +		id_mask = vlan_tci_vidm(rule); +		cfi = vlan_tci_cfi(rule); +		cfi_mask = vlan_tci_cfim(rule); +		prio = vlan_tci_prio(rule); +		prio_mask = vlan_tci_priom(rule);  		if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {  			vlan |= RQFPR_CFI; @@ -1567,9 +1580,6 @@ static int gfar_write_filer_table(struct gfar_private *priv,  	if (tab->index > MAX_FILER_IDX - 1)  		return -EBUSY; -	/* Avoid inconsistent filer table to be processed */ -	lock_rx_qs(priv); -  	/* Fill regular entries */  	for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl);  	     i++) @@ -1582,8 +1592,6 @@ static int gfar_write_filer_table(struct gfar_private *priv,  	 */  	gfar_write_filer(priv, i, 0x20, 0x0); -	unlock_rx_qs(priv); -  	return 0;  } @@ -1666,10 +1674,10 @@ static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow)  	for (i = 0; i < sizeof(flow->m_u); i++)  		flow->m_u.hdata[i] ^= 0xFF; -	flow->m_ext.vlan_etype ^= 0xFFFF; -	flow->m_ext.vlan_tci ^= 0xFFFF; -	flow->m_ext.data[0] ^= ~0; -	flow->m_ext.data[1] ^= ~0; +	flow->m_ext.vlan_etype ^= cpu_to_be16(0xFFFF); +	flow->m_ext.vlan_tci ^= cpu_to_be16(0xFFFF); +	flow->m_ext.data[0] ^= cpu_to_be32(~0); +	flow->m_ext.data[1] ^= cpu_to_be32(~0);  }  static int gfar_add_cls(struct gfar_private *priv, @@ -1788,6 +1796,9 @@ static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)  	struct gfar_private *priv = netdev_priv(dev);  	int ret = 0; +	if (test_bit(GFAR_RESETTING, &priv->state)) +		return -EBUSY; +  	mutex_lock(&priv->rx_queue_access);  	switch (cmd->cmd) { diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index e006a09ba89..bb568006f37 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -22,7 +22,6 @@  #include <linux/device.h>  #include <linux/hrtimer.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/module.h> @@ -134,7 +133,7 @@ struct gianfar_ptp_registers {  #define REG_SIZE	sizeof(struct gianfar_ptp_registers)  struct etsects { -	struct gianfar_ptp_registers *regs; +	struct gianfar_ptp_registers __iomem *regs;  	spinlock_t lock; /* protects regs */  	struct ptp_clock *clock;  	struct ptp_clock_info caps; @@ -415,6 +414,7 @@ static struct ptp_clock_info ptp_gianfar_caps = {  	.n_alarm	= 0,  	.n_ext_ts	= N_EXT_TS,  	.n_per_out	= 0, +	.n_pins		= 0,  	.pps		= 1,  	.adjfreq	= ptp_gianfar_adjfreq,  	.adjtime	= ptp_gianfar_adjtime, diff --git a/drivers/net/ethernet/freescale/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c deleted file mode 100644 index acb55af7e3f..00000000000 --- a/drivers/net/ethernet/freescale/gianfar_sysfs.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * drivers/net/ethernet/freescale/gianfar_sysfs.c - * - * Gianfar Ethernet Driver - * This driver is designed for the non-CPM ethernet controllers - * on the 85xx and 83xx family of integrated processors - * Based on 8260_io/fcc_enet.c - * - * Author: Andy Fleming - * Maintainer: Kumar Gala (galak@kernel.crashing.org) - * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> - * - * Copyright 2002-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute  it and/or modify it - * under  the terms of  the GNU General  Public License as published by the - * Free Software Foundation;  either version 2 of the  License, or (at your - * option) any later version. - * - * Sysfs file creation and management - */ - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/unistd.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/device.h> - -#include <asm/uaccess.h> -#include <linux/module.h> - -#include "gianfar.h" - -static ssize_t gfar_show_bd_stash(struct device *dev, -				  struct device_attribute *attr, char *buf) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - -	return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off"); -} - -static ssize_t gfar_set_bd_stash(struct device *dev, -				 struct device_attribute *attr, -				 const char *buf, size_t count) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	int new_setting = 0; -	u32 temp; -	unsigned long flags; - -	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) -		return count; - - -	/* Find out the new setting */ -	if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) -		new_setting = 1; -	else if (!strncmp("off", buf, count - 1) || -		 !strncmp("0", buf, count - 1)) -		new_setting = 0; -	else -		return count; - - -	local_irq_save(flags); -	lock_rx_qs(priv); - -	/* Set the new stashing value */ -	priv->bd_stash_en = new_setting; - -	temp = gfar_read(®s->attr); - -	if (new_setting) -		temp |= ATTR_BDSTASH; -	else -		temp &= ~(ATTR_BDSTASH); - -	gfar_write(®s->attr, temp); - -	unlock_rx_qs(priv); -	local_irq_restore(flags); - -	return count; -} - -static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash); - -static ssize_t gfar_show_rx_stash_size(struct device *dev, -				       struct device_attribute *attr, char *buf) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - -	return sprintf(buf, "%d\n", priv->rx_stash_size); -} - -static ssize_t gfar_set_rx_stash_size(struct device *dev, -				      struct device_attribute *attr, -				      const char *buf, size_t count) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	unsigned int length = simple_strtoul(buf, NULL, 0); -	u32 temp; -	unsigned long flags; - -	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) -		return count; - -	local_irq_save(flags); -	lock_rx_qs(priv); - -	if (length > priv->rx_buffer_size) -		goto out; - -	if (length == priv->rx_stash_size) -		goto out; - -	priv->rx_stash_size = length; - -	temp = gfar_read(®s->attreli); -	temp &= ~ATTRELI_EL_MASK; -	temp |= ATTRELI_EL(length); -	gfar_write(®s->attreli, temp); - -	/* Turn stashing on/off as appropriate */ -	temp = gfar_read(®s->attr); - -	if (length) -		temp |= ATTR_BUFSTASH; -	else -		temp &= ~(ATTR_BUFSTASH); - -	gfar_write(®s->attr, temp); - -out: -	unlock_rx_qs(priv); -	local_irq_restore(flags); - -	return count; -} - -static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size, -		   gfar_set_rx_stash_size); - -/* Stashing will only be enabled when rx_stash_size != 0 */ -static ssize_t gfar_show_rx_stash_index(struct device *dev, -					struct device_attribute *attr, -					char *buf) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - -	return sprintf(buf, "%d\n", priv->rx_stash_index); -} - -static ssize_t gfar_set_rx_stash_index(struct device *dev, -				       struct device_attribute *attr, -				       const char *buf, size_t count) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	unsigned short index = simple_strtoul(buf, NULL, 0); -	u32 temp; -	unsigned long flags; - -	if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) -		return count; - -	local_irq_save(flags); -	lock_rx_qs(priv); - -	if (index > priv->rx_stash_size) -		goto out; - -	if (index == priv->rx_stash_index) -		goto out; - -	priv->rx_stash_index = index; - -	temp = gfar_read(®s->attreli); -	temp &= ~ATTRELI_EI_MASK; -	temp |= ATTRELI_EI(index); -	gfar_write(®s->attreli, temp); - -out: -	unlock_rx_qs(priv); -	local_irq_restore(flags); - -	return count; -} - -static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index, -		   gfar_set_rx_stash_index); - -static ssize_t gfar_show_fifo_threshold(struct device *dev, -					struct device_attribute *attr, -					char *buf) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - -	return sprintf(buf, "%d\n", priv->fifo_threshold); -} - -static ssize_t gfar_set_fifo_threshold(struct device *dev, -				       struct device_attribute *attr, -				       const char *buf, size_t count) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	unsigned int length = simple_strtoul(buf, NULL, 0); -	u32 temp; -	unsigned long flags; - -	if (length > GFAR_MAX_FIFO_THRESHOLD) -		return count; - -	local_irq_save(flags); -	lock_tx_qs(priv); - -	priv->fifo_threshold = length; - -	temp = gfar_read(®s->fifo_tx_thr); -	temp &= ~FIFO_TX_THR_MASK; -	temp |= length; -	gfar_write(®s->fifo_tx_thr, temp); - -	unlock_tx_qs(priv); -	local_irq_restore(flags); - -	return count; -} - -static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold, -		   gfar_set_fifo_threshold); - -static ssize_t gfar_show_fifo_starve(struct device *dev, -				     struct device_attribute *attr, char *buf) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - -	return sprintf(buf, "%d\n", priv->fifo_starve); -} - -static ssize_t gfar_set_fifo_starve(struct device *dev, -				    struct device_attribute *attr, -				    const char *buf, size_t count) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	unsigned int num = simple_strtoul(buf, NULL, 0); -	u32 temp; -	unsigned long flags; - -	if (num > GFAR_MAX_FIFO_STARVE) -		return count; - -	local_irq_save(flags); -	lock_tx_qs(priv); - -	priv->fifo_starve = num; - -	temp = gfar_read(®s->fifo_tx_starve); -	temp &= ~FIFO_TX_STARVE_MASK; -	temp |= num; -	gfar_write(®s->fifo_tx_starve, temp); - -	unlock_tx_qs(priv); -	local_irq_restore(flags); - -	return count; -} - -static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, -		   gfar_set_fifo_starve); - -static ssize_t gfar_show_fifo_starve_off(struct device *dev, -					 struct device_attribute *attr, -					 char *buf) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); - -	return sprintf(buf, "%d\n", priv->fifo_starve_off); -} - -static ssize_t gfar_set_fifo_starve_off(struct device *dev, -					struct device_attribute *attr, -					const char *buf, size_t count) -{ -	struct gfar_private *priv = netdev_priv(to_net_dev(dev)); -	struct gfar __iomem *regs = priv->gfargrp[0].regs; -	unsigned int num = simple_strtoul(buf, NULL, 0); -	u32 temp; -	unsigned long flags; - -	if (num > GFAR_MAX_FIFO_STARVE_OFF) -		return count; - -	local_irq_save(flags); -	lock_tx_qs(priv); - -	priv->fifo_starve_off = num; - -	temp = gfar_read(®s->fifo_tx_starve_shutoff); -	temp &= ~FIFO_TX_STARVE_OFF_MASK; -	temp |= num; -	gfar_write(®s->fifo_tx_starve_shutoff, temp); - -	unlock_tx_qs(priv); -	local_irq_restore(flags); - -	return count; -} - -static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off, -		   gfar_set_fifo_starve_off); - -void gfar_init_sysfs(struct net_device *dev) -{ -	struct gfar_private *priv = netdev_priv(dev); -	int rc; - -	/* Initialize the default values */ -	priv->fifo_threshold = DEFAULT_FIFO_TX_THR; -	priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; -	priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; - -	/* Create our sysfs files */ -	rc = device_create_file(&dev->dev, &dev_attr_bd_stash); -	rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size); -	rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index); -	rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold); -	rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve); -	rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off); -	if (rc) -		dev_err(&dev->dev, "Error creating gianfar sysfs files\n"); -} diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 5930c39672d..36fc429298e 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -31,6 +31,8 @@  #include <linux/mii.h>  #include <linux/phy.h>  #include <linux/workqueue.h> +#include <linux/of_address.h> +#include <linux/of_irq.h>  #include <linux/of_mdio.h>  #include <linux/of_net.h>  #include <linux/of_platform.h> @@ -433,11 +435,6 @@ static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,  		     QE_CR_PROTOCOL_ETHERNET, 0);  } -static inline int compare_addr(u8 **addr1, u8 **addr2) -{ -	return memcmp(addr1, addr2, ETH_ALEN); -} -  #ifdef DEBUG  static void get_statistics(struct ucc_geth_private *ugeth,  			   struct ucc_geth_tx_firmware_statistics * @@ -1731,9 +1728,6 @@ static int init_phy(struct net_device *dev)  	phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,  				priv->phy_interface); -	if (!phydev) -		phydev = of_phy_connect_fixed_link(dev, &adjust_link, -						   priv->phy_interface);  	if (!phydev) {  		dev_err(&dev->dev, "Could not attach to PHY\n");  		return -ENODEV; @@ -2996,11 +2990,11 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)  	if (ug_info->rxExtendedFiltering) {  		size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;  		if (ug_info->largestexternallookupkeysize == -		    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) +		    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)  			size +=  			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;  		if (ug_info->largestexternallookupkeysize == -		    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) +		    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)  			size +=  			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;  	} @@ -3264,7 +3258,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)  		dev->stats.tx_packets++; -		dev_kfree_skb(skb); +		dev_consume_skb_any(skb);  		ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;  		ugeth->skb_dirtytx[txQ] = @@ -3793,6 +3787,17 @@ static int ucc_geth_probe(struct platform_device* ofdev)  	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);  	ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0); +	if (!ug_info->phy_node) { +		/* In the case of a fixed PHY, the DT node associated +		 * to the PHY is the Ethernet MAC DT node. +		 */ +		if (of_phy_is_fixed_link(np)) { +			err = of_phy_register_fixed_link(np); +			if (err) +				return err; +		} +		ug_info->phy_node = np; +	}  	/* Find the TBI PHY node.  If it's not there, we don't support SGMII */  	ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0); @@ -3899,7 +3904,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)  	mac_addr = of_get_mac_address(np);  	if (mac_addr) -		memcpy(dev->dev_addr, mac_addr, 6); +		memcpy(dev->dev_addr, mac_addr, ETH_ALEN);  	ugeth->ug_info = ug_info;  	ugeth->dev = device; diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c index e79aaf9ae52..cc83350d56b 100644 --- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c +++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c @@ -16,7 +16,6 @@   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/errno.h>  #include <linux/stddef.h>  #include <linux/interrupt.h> @@ -418,5 +417,5 @@ static const struct ethtool_ops uec_ethtool_ops = {  void uec_set_ethtool_ops(struct net_device *netdev)  { -	SET_ETHTOOL_OPS(netdev, &uec_ethtool_ops); +	netdev->ethtool_ops = &uec_ethtool_ops;  } diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index c1b6e7e31aa..0c9d55c862a 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -17,6 +17,7 @@  #include <linux/module.h>  #include <linux/phy.h>  #include <linux/mdio.h> +#include <linux/of_address.h>  #include <linux/of_platform.h>  #include <linux/of_mdio.h> @@ -161,7 +162,9 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)  	/* Return all Fs if nothing was there */  	if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) { -		dev_err(&bus->dev, "MDIO read error\n"); +		dev_err(&bus->dev, +			"Error while reading PHY%d reg at %d.%d\n", +			phy_id, dev_addr, regnum);  		return 0xffff;  	}  | 
