diff options
Diffstat (limited to 'drivers/net/ethernet/freescale')
| -rw-r--r-- | drivers/net/ethernet/freescale/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 145 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/fec_ptp.c | 16 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 95 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/fs_enet/fs_enet.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 17 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/gianfar.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/gianfar_ethtool.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/xgmac_mdio.c | 130 | 
10 files changed, 275 insertions, 139 deletions
| diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 270308315d43..ba84c4a9ce32 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -69,7 +69,8 @@ config FSL_XGMAC_MDIO  	select PHYLIB  	select OF_MDIO  	---help--- -	  This driver supports the MDIO bus on the Fman 10G Ethernet MACs. +	  This driver supports the MDIO bus on the Fman 10G Ethernet MACs, and +	  on the FMan mEMAC (which supports both Clauses 22 and 45)  config UCC_GETH  	tristate "Freescale QE Gigabit Ethernet" diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 40132929daf7..a86af8a7485d 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -16,6 +16,7 @@  #include <linux/clocksource.h>  #include <linux/net_tstamp.h>  #include <linux/ptp_clock_kernel.h> +#include <linux/timecounter.h>  #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \      defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ @@ -356,6 +357,7 @@ struct bufdesc_ex {  #define FEC_ENET_RXB    ((uint)0x01000000)      /* A buffer was received */  #define FEC_ENET_MII    ((uint)0x00800000)      /* MII interrupt */  #define FEC_ENET_EBERR  ((uint)0x00400000)      /* SDMA bus error */ +#define FEC_ENET_WAKEUP	((uint)0x00020000)	/* Wakeup request */  #define FEC_ENET_TXF	(FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2)  #define FEC_ENET_RXF	(FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2)  #define FEC_ENET_TS_AVAIL       ((uint)0x00010000) @@ -513,6 +515,7 @@ struct fec_enet_private {  	int	irq[FEC_IRQ_NUM];  	bool	bufdesc_ex;  	int	pause_flag; +	int	wol_flag;  	u32	quirks;  	struct	napi_struct napi; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index bba87775419d..9bb6220663b2 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -188,6 +188,9 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");  #define FEC_MMFR_RA(v)		((v & 0x1f) << 18)  #define FEC_MMFR_TA		(2 << 16)  #define FEC_MMFR_DATA(v)	(v & 0xffff) +/* FEC ECR bits definition */ +#define FEC_ECR_MAGICEN		(1 << 2) +#define FEC_ECR_SLEEP		(1 << 3)  #define FEC_MII_TIMEOUT		30000 /* us */ @@ -196,6 +199,9 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");  #define FEC_PAUSE_FLAG_AUTONEG	0x1  #define FEC_PAUSE_FLAG_ENABLE	0x2 +#define FEC_WOL_HAS_MAGIC_PACKET	(0x1 << 0) +#define FEC_WOL_FLAG_ENABLE		(0x1 << 1) +#define FEC_WOL_FLAG_SLEEP_ON		(0x1 << 2)  #define COPYBREAK_DEFAULT	256 @@ -1090,7 +1096,9 @@ static void  fec_stop(struct net_device *ndev)  {  	struct fec_enet_private *fep = netdev_priv(ndev); +	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;  	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8); +	u32 val;  	/* We cannot expect a graceful transmit stop without link !!! */  	if (fep->link) { @@ -1104,17 +1112,28 @@ fec_stop(struct net_device *ndev)  	 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC  	 * instead of reset MAC itself.  	 */ -	if (fep->quirks & FEC_QUIRK_HAS_AVB) { -		writel(0, fep->hwp + FEC_ECNTRL); +	if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { +		if (fep->quirks & FEC_QUIRK_HAS_AVB) { +			writel(0, fep->hwp + FEC_ECNTRL); +		} else { +			writel(1, fep->hwp + FEC_ECNTRL); +			udelay(10); +		} +		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);  	} else { -		writel(1, fep->hwp + FEC_ECNTRL); -		udelay(10); +		writel(FEC_DEFAULT_IMASK | FEC_ENET_WAKEUP, fep->hwp + FEC_IMASK); +		val = readl(fep->hwp + FEC_ECNTRL); +		val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); +		writel(val, fep->hwp + FEC_ECNTRL); + +		if (pdata && pdata->sleep_mode_enable) +			pdata->sleep_mode_enable(true);  	}  	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); -	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);  	/* We have to keep ENET enabled to have MII interrupt stay working */ -	if (fep->quirks & FEC_QUIRK_ENET_MAC) { +	if (fep->quirks & FEC_QUIRK_ENET_MAC && +		!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {  		writel(2, fep->hwp + FEC_ECNTRL);  		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);  	} @@ -1170,12 +1189,13 @@ static void  fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)  {  	struct	fec_enet_private *fep; -	struct bufdesc *bdp; +	struct bufdesc *bdp, *bdp_t;  	unsigned short status;  	struct	sk_buff	*skb;  	struct fec_enet_priv_tx_q *txq;  	struct netdev_queue *nq;  	int	index = 0; +	int	i, bdnum;  	int	entries_free;  	fep = netdev_priv(ndev); @@ -1196,18 +1216,29 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)  		if (bdp == txq->cur_tx)  			break; -		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); - +		bdp_t = bdp; +		bdnum = 1; +		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep);  		skb = txq->tx_skbuff[index]; -		txq->tx_skbuff[index] = NULL; -		if (!IS_TSO_HEADER(txq, 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, queue_id); -			continue; +		while (!skb) { +			bdp_t = fec_enet_get_nextdesc(bdp_t, fep, queue_id); +			index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep); +			skb = txq->tx_skbuff[index]; +			bdnum++;  		} +		if (skb_shinfo(skb)->nr_frags && +		    (status = bdp_t->cbd_sc) & BD_ENET_TX_READY) +			break; + +		for (i = 0; i < bdnum; i++) { +			if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr)) +				dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, +						 bdp->cbd_datlen, DMA_TO_DEVICE); +			bdp->cbd_bufaddr = 0; +			if (i < bdnum - 1) +				bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); +		} +		txq->tx_skbuff[index] = NULL;  		/* Check for errors. */  		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | @@ -2428,6 +2459,44 @@ static int fec_enet_set_tunable(struct net_device *netdev,  	return ret;  } +static void +fec_enet_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); + +	if (fep->wol_flag & FEC_WOL_HAS_MAGIC_PACKET) { +		wol->supported = WAKE_MAGIC; +		wol->wolopts = fep->wol_flag & FEC_WOL_FLAG_ENABLE ? WAKE_MAGIC : 0; +	} else { +		wol->supported = wol->wolopts = 0; +	} +} + +static int +fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +{ +	struct fec_enet_private *fep = netdev_priv(ndev); + +	if (!(fep->wol_flag & FEC_WOL_HAS_MAGIC_PACKET)) +		return -EINVAL; + +	if (wol->wolopts & ~WAKE_MAGIC) +		return -EINVAL; + +	device_set_wakeup_enable(&ndev->dev, wol->wolopts & WAKE_MAGIC); +	if (device_may_wakeup(&ndev->dev)) { +		fep->wol_flag |= FEC_WOL_FLAG_ENABLE; +		if (fep->irq[0] > 0) +			enable_irq_wake(fep->irq[0]); +	} else { +		fep->wol_flag &= (~FEC_WOL_FLAG_ENABLE); +		if (fep->irq[0] > 0) +			disable_irq_wake(fep->irq[0]); +	} + +	return 0; +} +  static const struct ethtool_ops fec_enet_ethtool_ops = {  	.get_settings		= fec_enet_get_settings,  	.set_settings		= fec_enet_set_settings, @@ -2446,6 +2515,8 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {  	.get_ts_info		= fec_enet_get_ts_info,  	.get_tunable		= fec_enet_get_tunable,  	.set_tunable		= fec_enet_set_tunable, +	.get_wol		= fec_enet_get_wol, +	.set_wol		= fec_enet_set_wol,  };  static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) @@ -2525,12 +2596,9 @@ static void fec_enet_free_queue(struct net_device *ndev)  		}  	for (i = 0; i < fep->num_rx_queues; i++) -		if (fep->rx_queue[i]) -			kfree(fep->rx_queue[i]); - +		kfree(fep->rx_queue[i]);  	for (i = 0; i < fep->num_tx_queues; i++) -		if (fep->tx_queue[i]) -			kfree(fep->tx_queue[i]); +		kfree(fep->tx_queue[i]);  }  static int fec_enet_alloc_queue(struct net_device *ndev) @@ -2706,6 +2774,9 @@ fec_enet_open(struct net_device *ndev)  	phy_start(fep->phy_dev);  	netif_tx_start_all_queues(ndev); +	device_set_wakeup_enable(&ndev->dev, fep->wol_flag & +				 FEC_WOL_FLAG_ENABLE); +  	return 0;  err_enet_mii_probe: @@ -3155,6 +3226,9 @@ fec_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, ndev); +	if (of_get_property(np, "fsl,magic-packet", NULL)) +		fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET; +  	phy_node = of_parse_phandle(np, "phy-handle", 0);  	if (!phy_node && of_phy_is_fixed_link(np)) {  		ret = of_phy_register_fixed_link(np); @@ -3249,6 +3323,8 @@ fec_probe(struct platform_device *pdev)  				       0, pdev->name, ndev);  		if (ret)  			goto failed_irq; + +		fep->irq[i] = irq;  	}  	init_completion(&fep->mdio_done); @@ -3265,6 +3341,9 @@ fec_probe(struct platform_device *pdev)  	if (ret)  		goto failed_register; +	device_init_wakeup(&ndev->dev, fep->wol_flag & +			   FEC_WOL_HAS_MAGIC_PACKET); +  	if (fep->bufdesc_ex && fep->ptp_clock)  		netdev_info(ndev, "registered PHC device %d\n", fep->dev_id); @@ -3318,6 +3397,8 @@ static int __maybe_unused fec_suspend(struct device *dev)  	rtnl_lock();  	if (netif_running(ndev)) { +		if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) +			fep->wol_flag |= FEC_WOL_FLAG_SLEEP_ON;  		phy_stop(fep->phy_dev);  		napi_disable(&fep->napi);  		netif_tx_lock_bh(ndev); @@ -3325,11 +3406,12 @@ static int __maybe_unused fec_suspend(struct device *dev)  		netif_tx_unlock_bh(ndev);  		fec_stop(ndev);  		fec_enet_clk_enable(ndev, false); -		pinctrl_pm_select_sleep_state(&fep->pdev->dev); +		if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) +			pinctrl_pm_select_sleep_state(&fep->pdev->dev);  	}  	rtnl_unlock(); -	if (fep->reg_phy) +	if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE))  		regulator_disable(fep->reg_phy);  	/* SOC supply clock to phy, when clock is disabled, phy link down @@ -3345,9 +3427,11 @@ static int __maybe_unused fec_resume(struct device *dev)  {  	struct net_device *ndev = dev_get_drvdata(dev);  	struct fec_enet_private *fep = netdev_priv(ndev); +	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;  	int ret; +	int val; -	if (fep->reg_phy) { +	if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) {  		ret = regulator_enable(fep->reg_phy);  		if (ret)  			return ret; @@ -3355,12 +3439,21 @@ static int __maybe_unused fec_resume(struct device *dev)  	rtnl_lock();  	if (netif_running(ndev)) { -		pinctrl_pm_select_default_state(&fep->pdev->dev);  		ret = fec_enet_clk_enable(ndev, true);  		if (ret) {  			rtnl_unlock();  			goto failed_clk;  		} +		if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) { +			if (pdata && pdata->sleep_mode_enable) +				pdata->sleep_mode_enable(false); +			val = readl(fep->hwp + FEC_ECNTRL); +			val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP); +			writel(val, fep->hwp + FEC_ECNTRL); +			fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON; +		} else { +			pinctrl_pm_select_default_state(&fep->pdev->dev); +		}  		fec_restart(ndev);  		netif_tx_lock_bh(ndev);  		netif_device_attach(ndev); diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 992c8c3db553..1f9cf2345266 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -374,23 +374,9 @@ static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)  	struct fec_enet_private *fep =  	    container_of(ptp, struct fec_enet_private, ptp_caps);  	unsigned long flags; -	u64 now; -	u32 counter;  	spin_lock_irqsave(&fep->tmreg_lock, flags); - -	now = timecounter_read(&fep->tc); -	now += delta; - -	/* Get the timer value based on adjusted timestamp. -	 * Update the counter with the masked value. -	 */ -	counter = now & fep->cc.mask; -	writel(counter, fep->hwp + FEC_ATIME); - -	/* reset the timecounter */ -	timecounter_init(&fep->tc, &fep->cc, now); - +	timecounter_adjtime(&fep->tc, delta);  	spin_unlock_irqrestore(&fep->tmreg_lock, flags);  	return 0; 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 9e2bcb807923..a17628769a1f 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -278,14 +278,20 @@ static int fs_enet_tx_napi(struct napi_struct *napi, int budget)  			fep->stats.collisions++;  		/* unmap */ -		dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), -				skb->len, DMA_TO_DEVICE); +		if (fep->mapped_as_page[dirtyidx]) +			dma_unmap_page(fep->dev, CBDR_BUFADDR(bdp), +				       CBDR_DATLEN(bdp), DMA_TO_DEVICE); +		else +			dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), +					 CBDR_DATLEN(bdp), DMA_TO_DEVICE);  		/*  		 * Free the sk buffer associated with this last transmit.  		 */ -		dev_kfree_skb(skb); -		fep->tx_skbuff[dirtyidx] = NULL; +		if (skb) { +			dev_kfree_skb(skb); +			fep->tx_skbuff[dirtyidx] = NULL; +		}  		/*  		 * Update pointer to next buffer descriptor to be transmitted. @@ -299,7 +305,7 @@ static int fs_enet_tx_napi(struct napi_struct *napi, int budget)  		 * Since we have freed up a buffer, the ring is no longer  		 * full.  		 */ -		if (!fep->tx_free++) +		if (++fep->tx_free >= MAX_SKB_FRAGS)  			do_wake = 1;  		has_tx_work = 1;  	} @@ -509,6 +515,9 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)  	cbd_t __iomem *bdp;  	int curidx;  	u16 sc; +	int nr_frags = skb_shinfo(skb)->nr_frags; +	skb_frag_t *frag; +	int len;  #ifdef CONFIG_FS_ENET_MPC5121_FEC  	if (((unsigned long)skb->data) & 0x3) { @@ -530,7 +539,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)  	 */  	bdp = fep->cur_tx; -	if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) { +	if (fep->tx_free <= nr_frags || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {  		netif_stop_queue(dev);  		spin_unlock(&fep->tx_lock); @@ -543,35 +552,42 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)  	}  	curidx = bdp - fep->tx_bd_base; -	/* -	 * Clear all of the status flags. -	 */ -	CBDC_SC(bdp, BD_ENET_TX_STATS); - -	/* -	 * Save skb pointer. -	 */ -	fep->tx_skbuff[curidx] = skb; - -	fep->stats.tx_bytes += skb->len; +	len = skb->len; +	fep->stats.tx_bytes += len; +	if (nr_frags) +		len -= skb->data_len; +	fep->tx_free -= nr_frags + 1;  	/*  	 * Push the data cache so the CPM does not get stale memory data.  	 */  	CBDW_BUFADDR(bdp, dma_map_single(fep->dev, -				skb->data, skb->len, DMA_TO_DEVICE)); -	CBDW_DATLEN(bdp, skb->len); +				skb->data, len, DMA_TO_DEVICE)); +	CBDW_DATLEN(bdp, len); + +	fep->mapped_as_page[curidx] = 0; +	frag = skb_shinfo(skb)->frags; +	while (nr_frags) { +		CBDC_SC(bdp, +			BD_ENET_TX_STATS | BD_ENET_TX_LAST | BD_ENET_TX_TC); +		CBDS_SC(bdp, BD_ENET_TX_READY); + +		if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) +			bdp++, curidx++; +		else +			bdp = fep->tx_bd_base, curidx = 0; -	/* -	 * If this was the last BD in the ring, start at the beginning again. -	 */ -	if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) -		fep->cur_tx++; -	else -		fep->cur_tx = fep->tx_bd_base; +		len = skb_frag_size(frag); +		CBDW_BUFADDR(bdp, skb_frag_dma_map(fep->dev, frag, 0, len, +						   DMA_TO_DEVICE)); +		CBDW_DATLEN(bdp, len); -	if (!--fep->tx_free) -		netif_stop_queue(dev); +		fep->tx_skbuff[curidx] = NULL; +		fep->mapped_as_page[curidx] = 1; + +		frag++; +		nr_frags--; +	}  	/* Trigger transmission start */  	sc = BD_ENET_TX_READY | BD_ENET_TX_INTR | @@ -582,8 +598,22 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)  	 * yay for hw reuse :) */  	if (skb->len <= 60)  		sc |= BD_ENET_TX_PAD; +	CBDC_SC(bdp, BD_ENET_TX_STATS);  	CBDS_SC(bdp, sc); +	/* Save skb pointer. */ +	fep->tx_skbuff[curidx] = skb; + +	/* If this was the last BD in the ring, start at the beginning again. */ +	if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) +		bdp++; +	else +		bdp = fep->tx_bd_base; +	fep->cur_tx = bdp; + +	if (fep->tx_free < MAX_SKB_FRAGS) +		netif_stop_queue(dev); +  	skb_tx_timestamp(skb);  	(*fep->ops->tx_kickstart)(dev); @@ -917,7 +947,7 @@ static int fs_enet_probe(struct platform_device *ofdev)  	}  	fpi->rx_ring = 32; -	fpi->tx_ring = 32; +	fpi->tx_ring = 64;  	fpi->rx_copybreak = 240;  	fpi->napi_weight = 17;  	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); @@ -955,7 +985,8 @@ static int fs_enet_probe(struct platform_device *ofdev)  	privsize = sizeof(*fep) +  	           sizeof(struct sk_buff **) * -	           (fpi->rx_ring + fpi->tx_ring); +		     (fpi->rx_ring + fpi->tx_ring) + +		   sizeof(char) * fpi->tx_ring;  	ndev = alloc_etherdev(privsize);  	if (!ndev) { @@ -978,6 +1009,8 @@ static int fs_enet_probe(struct platform_device *ofdev)  	fep->rx_skbuff = (struct sk_buff **)&fep[1];  	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring; +	fep->mapped_as_page = (char *)(fep->rx_skbuff + fpi->rx_ring + +				       fpi->tx_ring);  	spin_lock_init(&fep->lock);  	spin_lock_init(&fep->tx_lock); @@ -1007,6 +1040,8 @@ static int fs_enet_probe(struct platform_device *ofdev)  	netif_carrier_off(ndev); +	ndev->features |= NETIF_F_SG; +  	ret = register_netdev(ndev);  	if (ret)  		goto out_free_bd; diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h index 3a4b49e0e717..f184d8f952e2 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h @@ -134,6 +134,7 @@ struct fs_enet_private {  	void __iomem *ring_base;  	struct sk_buff **rx_skbuff;  	struct sk_buff **tx_skbuff; +	char *mapped_as_page;  	cbd_t __iomem *rx_bd_base;	/* Address of Rx and Tx buffers.    */  	cbd_t __iomem *tx_bd_base;  	cbd_t __iomem *dirty_tx;	/* ring entries to be free()ed.     */ diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 5645342f5b28..43df78882e48 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -116,7 +116,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);  static void gfar_reset_task(struct work_struct *work);  static void gfar_timeout(struct net_device *dev);  static int gfar_close(struct net_device *dev); -struct sk_buff *gfar_new_skb(struct net_device *dev, dma_addr_t *bufaddr); +static struct sk_buff *gfar_new_skb(struct net_device *dev, +				    dma_addr_t *bufaddr);  static int gfar_set_mac_address(struct net_device *dev);  static int gfar_change_mtu(struct net_device *dev, int new_mtu);  static irqreturn_t gfar_error(int irq, void *dev_id); @@ -176,7 +177,7 @@ static int gfar_init_bds(struct net_device *ndev)  	struct gfar_priv_rx_q *rx_queue = NULL;  	struct txbd8 *txbdp;  	struct rxbd8 *rxbdp; -	u32 *rfbptr; +	u32 __iomem *rfbptr;  	int i, j;  	dma_addr_t bufaddr; @@ -554,7 +555,7 @@ static void gfar_ints_enable(struct gfar_private *priv)  	}  } -void lock_tx_qs(struct gfar_private *priv) +static void lock_tx_qs(struct gfar_private *priv)  {  	int i; @@ -562,7 +563,7 @@ void lock_tx_qs(struct gfar_private *priv)  		spin_lock(&priv->tx_queue[i]->txlock);  } -void unlock_tx_qs(struct gfar_private *priv) +static void unlock_tx_qs(struct gfar_private *priv)  {  	int i; @@ -763,7 +764,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)  	u32 *tx_queues, *rx_queues;  	unsigned short mode, poll_mode; -	if (!np || !of_device_is_available(np)) +	if (!np)  		return -ENODEV;  	if (of_device_is_compatible(np, "fsl,etsec2")) { @@ -2169,7 +2170,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb,  void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)  {  	fcb->flags |= TXFCB_VLN; -	fcb->vlctl = vlan_tx_tag_get(skb); +	fcb->vlctl = skb_vlan_tag_get(skb);  }  static inline struct txbd8 *skip_txbd(struct txbd8 *bdp, int stride, @@ -2229,7 +2230,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)  	regs = tx_queue->grp->regs;  	do_csum = (CHECKSUM_PARTIAL == skb->ip_summed); -	do_vlan = vlan_tx_tag_present(skb); +	do_vlan = skb_vlan_tag_present(skb);  	do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&  		    priv->hwts_tx_en; @@ -2671,7 +2672,7 @@ static struct sk_buff *gfar_alloc_skb(struct net_device *dev)  	return skb;  } -struct sk_buff *gfar_new_skb(struct net_device *dev, dma_addr_t *bufaddr) +static struct sk_buff *gfar_new_skb(struct net_device *dev, dma_addr_t *bufaddr)  {  	struct gfar_private *priv = netdev_priv(dev);  	struct sk_buff *skb; diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index b581b8823a2a..9e1802400c23 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1039,7 +1039,7 @@ struct gfar_priv_rx_q {  	/* RX Coalescing values */  	unsigned char rxcoalescing;  	unsigned long rxic; -	u32 *rfbptr; +	u32 __iomem *rfbptr;  };  enum gfar_irqinfo_id { diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 3e1a9c1a67a9..fda12fb32ec7 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1586,7 +1586,7 @@ static int gfar_write_filer_table(struct gfar_private *priv,  		return -EBUSY;  	/* Fill regular entries */ -	for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); +	for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].prop);  	     i++)  		gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);  	/* Fill the rest with fall-troughs */ diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index 6e7db66069aa..3a83bc2c613c 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -32,18 +32,19 @@ struct tgec_mdio_controller {  	__be32	mdio_addr;	/* MDIO address */  } __packed; +#define MDIO_STAT_ENC		BIT(6)  #define MDIO_STAT_CLKDIV(x)	(((x>>1) & 0xff) << 8) -#define MDIO_STAT_BSY		(1 << 0) -#define MDIO_STAT_RD_ER		(1 << 1) +#define MDIO_STAT_BSY		BIT(0) +#define MDIO_STAT_RD_ER		BIT(1)  #define MDIO_CTL_DEV_ADDR(x) 	(x & 0x1f)  #define MDIO_CTL_PORT_ADDR(x)	((x & 0x1f) << 5) -#define MDIO_CTL_PRE_DIS	(1 << 10) -#define MDIO_CTL_SCAN_EN	(1 << 11) -#define MDIO_CTL_POST_INC	(1 << 14) -#define MDIO_CTL_READ		(1 << 15) +#define MDIO_CTL_PRE_DIS	BIT(10) +#define MDIO_CTL_SCAN_EN	BIT(11) +#define MDIO_CTL_POST_INC	BIT(14) +#define MDIO_CTL_READ		BIT(15)  #define MDIO_DATA(x)		(x & 0xffff) -#define MDIO_DATA_BSY		(1 << 31) +#define MDIO_DATA_BSY		BIT(31)  /*   * Wait until the MDIO bus is free @@ -51,12 +52,16 @@ struct tgec_mdio_controller {  static int xgmac_wait_until_free(struct device *dev,  				 struct tgec_mdio_controller __iomem *regs)  { -	uint32_t status; +	unsigned int timeout;  	/* Wait till the bus is free */ -	status = spin_event_timeout( -		!((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY), TIMEOUT, 0); -	if (!status) { +	timeout = TIMEOUT; +	while ((ioread32be(®s->mdio_stat) & MDIO_STAT_BSY) && timeout) { +		cpu_relax(); +		timeout--; +	} + +	if (!timeout) {  		dev_err(dev, "timeout waiting for bus to be free\n");  		return -ETIMEDOUT;  	} @@ -70,12 +75,16 @@ static int xgmac_wait_until_free(struct device *dev,  static int xgmac_wait_until_done(struct device *dev,  				 struct tgec_mdio_controller __iomem *regs)  { -	uint32_t status; +	unsigned int timeout;  	/* Wait till the MDIO write is complete */ -	status = spin_event_timeout( -		!((in_be32(®s->mdio_data)) & MDIO_DATA_BSY), TIMEOUT, 0); -	if (!status) { +	timeout = TIMEOUT; +	while ((ioread32be(®s->mdio_data) & MDIO_DATA_BSY) && timeout) { +		cpu_relax(); +		timeout--; +	} + +	if (!timeout) {  		dev_err(dev, "timeout waiting for operation to complete\n");  		return -ETIMEDOUT;  	} @@ -91,29 +100,42 @@ static int xgmac_wait_until_done(struct device *dev,  static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)  {  	struct tgec_mdio_controller __iomem *regs = bus->priv; -	uint16_t dev_addr = regnum >> 16; +	uint16_t dev_addr; +	u32 mdio_ctl, mdio_stat;  	int ret; -	/* Setup the MII Mgmt clock speed */ -	out_be32(®s->mdio_stat, MDIO_STAT_CLKDIV(100)); +	mdio_stat = ioread32be(®s->mdio_stat); +	if (regnum & MII_ADDR_C45) { +		/* Clause 45 (ie 10G) */ +		dev_addr = (regnum >> 16) & 0x1f; +		mdio_stat |= MDIO_STAT_ENC; +	} else { +		/* Clause 22 (ie 1G) */ +		dev_addr = regnum & 0x1f; +		mdio_stat &= ~MDIO_STAT_ENC; +	} + +	iowrite32be(mdio_stat, ®s->mdio_stat);  	ret = xgmac_wait_until_free(&bus->dev, regs);  	if (ret)  		return ret;  	/* Set the port and dev addr */ -	out_be32(®s->mdio_ctl, -		 MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr)); +	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); +	iowrite32be(mdio_ctl, ®s->mdio_ctl);  	/* Set the register address */ -	out_be32(®s->mdio_addr, regnum & 0xffff); +	if (regnum & MII_ADDR_C45) { +		iowrite32be(regnum & 0xffff, ®s->mdio_addr); -	ret = xgmac_wait_until_free(&bus->dev, regs); -	if (ret) -		return ret; +		ret = xgmac_wait_until_free(&bus->dev, regs); +		if (ret) +			return ret; +	}  	/* Write the value to the register */ -	out_be32(®s->mdio_data, MDIO_DATA(value)); +	iowrite32be(MDIO_DATA(value), ®s->mdio_data);  	ret = xgmac_wait_until_done(&bus->dev, regs);  	if (ret) @@ -130,13 +152,22 @@ static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 val  static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)  {  	struct tgec_mdio_controller __iomem *regs = bus->priv; -	uint16_t dev_addr = regnum >> 16; +	uint16_t dev_addr; +	uint32_t mdio_stat;  	uint32_t mdio_ctl;  	uint16_t value;  	int ret; -	/* Setup the MII Mgmt clock speed */ -	out_be32(®s->mdio_stat, MDIO_STAT_CLKDIV(100)); +	mdio_stat = ioread32be(®s->mdio_stat); +	if (regnum & MII_ADDR_C45) { +		dev_addr = (regnum >> 16) & 0x1f; +		mdio_stat |= MDIO_STAT_ENC; +	} else { +		dev_addr = regnum & 0x1f; +		mdio_stat &= ~MDIO_STAT_ENC; +	} + +	iowrite32be(mdio_stat, ®s->mdio_stat);  	ret = xgmac_wait_until_free(&bus->dev, regs);  	if (ret) @@ -144,54 +175,38 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)  	/* Set the Port and Device Addrs */  	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); -	out_be32(®s->mdio_ctl, mdio_ctl); +	iowrite32be(mdio_ctl, ®s->mdio_ctl);  	/* Set the register address */ -	out_be32(®s->mdio_addr, regnum & 0xffff); +	if (regnum & MII_ADDR_C45) { +		iowrite32be(regnum & 0xffff, ®s->mdio_addr); -	ret = xgmac_wait_until_free(&bus->dev, regs); -	if (ret) -		return ret; +		ret = xgmac_wait_until_free(&bus->dev, regs); +		if (ret) +			return ret; +	}  	/* Initiate the read */ -	out_be32(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ); +	iowrite32be(mdio_ctl | MDIO_CTL_READ, ®s->mdio_ctl);  	ret = xgmac_wait_until_done(&bus->dev, regs);  	if (ret)  		return ret;  	/* Return all Fs if nothing was there */ -	if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) { +	if (ioread32be(®s->mdio_stat) & MDIO_STAT_RD_ER) {  		dev_err(&bus->dev,  			"Error while reading PHY%d reg at %d.%hhu\n",  			phy_id, dev_addr, regnum);  		return 0xffff;  	} -	value = in_be32(®s->mdio_data) & 0xffff; +	value = ioread32be(®s->mdio_data) & 0xffff;  	dev_dbg(&bus->dev, "read %04x\n", value);  	return value;  } -/* Reset the MIIM registers, and wait for the bus to free */ -static int xgmac_mdio_reset(struct mii_bus *bus) -{ -	struct tgec_mdio_controller __iomem *regs = bus->priv; -	int ret; - -	mutex_lock(&bus->mdio_lock); - -	/* Setup the MII Mgmt clock speed */ -	out_be32(®s->mdio_stat, MDIO_STAT_CLKDIV(100)); - -	ret = xgmac_wait_until_free(&bus->dev, regs); - -	mutex_unlock(&bus->mdio_lock); - -	return ret; -} -  static int xgmac_mdio_probe(struct platform_device *pdev)  {  	struct device_node *np = pdev->dev.of_node; @@ -205,15 +220,13 @@ static int xgmac_mdio_probe(struct platform_device *pdev)  		return ret;  	} -	bus = mdiobus_alloc_size(PHY_MAX_ADDR * sizeof(int)); +	bus = mdiobus_alloc();  	if (!bus)  		return -ENOMEM;  	bus->name = "Freescale XGMAC MDIO Bus";  	bus->read = xgmac_mdio_read;  	bus->write = xgmac_mdio_write; -	bus->reset = xgmac_mdio_reset; -	bus->irq = bus->priv;  	bus->parent = &pdev->dev;  	snprintf(bus->id, MII_BUS_ID_SIZE, "%llx", (unsigned long long)res.start); @@ -258,6 +271,9 @@ static struct of_device_id xgmac_mdio_match[] = {  	{  		.compatible = "fsl,fman-xmdio",  	}, +	{ +		.compatible = "fsl,fman-memac-mdio", +	},  	{},  };  MODULE_DEVICE_TABLE(of, xgmac_mdio_match); |