diff options
Diffstat (limited to 'drivers/net/ethernet/marvell')
| -rw-r--r-- | drivers/net/ethernet/marvell/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/mv643xx_eth.c | 417 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/mvmdio.c | 146 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/mvneta.c | 790 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/pxa168_eth.c | 29 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/skge.c | 25 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/sky2.c | 46 | 
7 files changed, 914 insertions, 546 deletions
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig index a49e81bdf8e..68e6a6613e9 100644 --- a/drivers/net/ethernet/marvell/Kconfig +++ b/drivers/net/ethernet/marvell/Kconfig @@ -33,6 +33,7 @@ config MV643XX_ETH  config MVMDIO  	tristate "Marvell MDIO interface support" +	depends on HAS_IOMEM  	select PHYLIB  	---help---  	  This driver supports the MDIO interface found in the network @@ -42,12 +43,12 @@ config MVMDIO  	  This driver is used by the MV643XX_ETH and MVNETA drivers.  config MVNETA -	tristate "Marvell Armada 370/XP network interface support" -	depends on MACH_ARMADA_370_XP +	tristate "Marvell Armada 370/38x/XP network interface support" +	depends on PLAT_ORION  	select MVMDIO  	---help---  	  This driver supports the network interface units in the -	  Marvell ARMADA XP and ARMADA 370 SoC family. +	  Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.  	  Note that this driver is distinct from the mv643xx_eth  	  driver, which should be used for the older Marvell SoCs diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 7fb5677451f..b151a949f35 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -33,8 +33,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -43,6 +42,7 @@  #include <linux/dma-mapping.h>  #include <linux/in.h>  #include <linux/ip.h> +#include <net/tso.h>  #include <linux/tcp.h>  #include <linux/udp.h>  #include <linux/etherdevice.h> @@ -180,10 +180,18 @@ static char mv643xx_eth_driver_version[] = "1.4";   * Misc definitions.   */  #define DEFAULT_RX_QUEUE_SIZE	128 -#define DEFAULT_TX_QUEUE_SIZE	256 +#define DEFAULT_TX_QUEUE_SIZE	512  #define SKB_DMA_REALIGN		((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) +#define TSO_HEADER_SIZE		128 +/* Max number of allowed TCP segments for software TSO */ +#define MV643XX_MAX_TSO_SEGS 100 +#define MV643XX_MAX_SKB_DESCS (MV643XX_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))  /*   * RX/TX descriptors.   */ @@ -251,6 +259,7 @@ struct tx_desc {  #define GEN_TCP_UDP_CHECKSUM		0x00020000  #define UDP_FRAME			0x00010000  #define MAC_HDR_EXTRA_4_BYTES		0x00008000 +#define GEN_TCP_UDP_CHK_FULL		0x00000400  #define MAC_HDR_EXTRA_8_BYTES		0x00000200  #define TX_IHL_SHIFT			11 @@ -346,6 +355,12 @@ struct tx_queue {  	int tx_curr_desc;  	int tx_used_desc; +	int tx_stop_threshold; +	int tx_wake_threshold; + +	char *tso_hdrs; +	dma_addr_t tso_hdrs_dma; +  	struct tx_desc *tx_desc_area;  	dma_addr_t tx_desc_dma;  	int tx_desc_area_size; @@ -492,7 +507,7 @@ static void txq_maybe_wake(struct tx_queue *txq)  	if (netif_tx_queue_stopped(nq)) {  		__netif_tx_lock(nq, smp_processor_id()); -		if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) +		if (txq->tx_desc_count <= txq->tx_wake_threshold)  			netif_tx_wake_queue(nq);  		__netif_tx_unlock(nq);  	} @@ -662,6 +677,198 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)  	return 0;  } +static inline __be16 sum16_as_be(__sum16 sum) +{ +	return (__force __be16)sum; +} + +static int skb_tx_csum(struct mv643xx_eth_private *mp, struct sk_buff *skb, +		       u16 *l4i_chk, u32 *command, int length) +{ +	int ret; +	u32 cmd = 0; + +	if (skb->ip_summed == CHECKSUM_PARTIAL) { +		int hdr_len; +		int tag_bytes; + +		BUG_ON(skb->protocol != htons(ETH_P_IP) && +		       skb->protocol != htons(ETH_P_8021Q)); + +		hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; +		tag_bytes = hdr_len - ETH_HLEN; + +		if (length - hdr_len > mp->shared->tx_csum_limit || +		    unlikely(tag_bytes & ~12)) { +			ret = skb_checksum_help(skb); +			if (!ret) +				goto no_csum; +			return ret; +		} + +		if (tag_bytes & 4) +			cmd |= MAC_HDR_EXTRA_4_BYTES; +		if (tag_bytes & 8) +			cmd |= MAC_HDR_EXTRA_8_BYTES; + +		cmd |= GEN_TCP_UDP_CHECKSUM | GEN_TCP_UDP_CHK_FULL | +			   GEN_IP_V4_CHECKSUM   | +			   ip_hdr(skb)->ihl << TX_IHL_SHIFT; + +		/* TODO: Revisit this. With the usage of GEN_TCP_UDP_CHK_FULL +		 * it seems we don't need to pass the initial checksum. */ +		switch (ip_hdr(skb)->protocol) { +		case IPPROTO_UDP: +			cmd |= UDP_FRAME; +			*l4i_chk = 0; +			break; +		case IPPROTO_TCP: +			*l4i_chk = 0; +			break; +		default: +			WARN(1, "protocol not supported"); +		} +	} else { +no_csum: +		/* Errata BTS #50, IHL must be 5 if no HW checksum */ +		cmd |= 5 << TX_IHL_SHIFT; +	} +	*command = cmd; +	return 0; +} + +static inline int +txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, +		 struct sk_buff *skb, char *data, int length, +		 bool last_tcp, bool is_last) +{ +	int tx_index; +	u32 cmd_sts; +	struct tx_desc *desc; + +	tx_index = txq->tx_curr_desc++; +	if (txq->tx_curr_desc == txq->tx_ring_size) +		txq->tx_curr_desc = 0; +	desc = &txq->tx_desc_area[tx_index]; + +	desc->l4i_chk = 0; +	desc->byte_cnt = length; +	desc->buf_ptr = dma_map_single(dev->dev.parent, data, +				       length, DMA_TO_DEVICE); +	if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) { +		WARN(1, "dma_map_single failed!\n"); +		return -ENOMEM; +	} + +	cmd_sts = BUFFER_OWNED_BY_DMA; +	if (last_tcp) { +		/* last descriptor in the TCP packet */ +		cmd_sts |= ZERO_PADDING | TX_LAST_DESC; +		/* last descriptor in SKB */ +		if (is_last) +			cmd_sts |= TX_ENABLE_INTERRUPT; +	} +	desc->cmd_sts = cmd_sts; +	return 0; +} + +static inline void +txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) +{ +	struct mv643xx_eth_private *mp = txq_to_mp(txq); +	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); +	int tx_index; +	struct tx_desc *desc; +	int ret; +	u32 cmd_csum = 0; +	u16 l4i_chk = 0; + +	tx_index = txq->tx_curr_desc; +	desc = &txq->tx_desc_area[tx_index]; + +	ret = skb_tx_csum(mp, skb, &l4i_chk, &cmd_csum, length); +	if (ret) +		WARN(1, "failed to prepare checksum!"); + +	/* Should we set this? Can't use the value from skb_tx_csum() +	 * as it's not the correct initial L4 checksum to use. */ +	desc->l4i_chk = 0; + +	desc->byte_cnt = hdr_len; +	desc->buf_ptr = txq->tso_hdrs_dma + +			txq->tx_curr_desc * TSO_HEADER_SIZE; +	desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA  | TX_FIRST_DESC | +				   GEN_CRC; + +	txq->tx_curr_desc++; +	if (txq->tx_curr_desc == txq->tx_ring_size) +		txq->tx_curr_desc = 0; +} + +static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, +			  struct net_device *dev) +{ +	struct mv643xx_eth_private *mp = txq_to_mp(txq); +	int total_len, data_left, ret; +	int desc_count = 0; +	struct tso_t tso; +	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + +	/* Count needed descriptors */ +	if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) { +		netdev_dbg(dev, "not enough descriptors for TSO!\n"); +		return -EBUSY; +	} + +	/* 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; + +		data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); +		total_len -= data_left; +		desc_count++; + +		/* prepare packet headers: MAC + IP + TCP */ +		hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE; +		tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); +		txq_put_hdr_tso(skb, txq, data_left); + +		while (data_left > 0) { +			int size; +			desc_count++; + +			size = min_t(int, tso.size, data_left); +			ret = txq_put_data_tso(dev, txq, skb, tso.data, size, +					       size == data_left, +					       total_len == 0); +			if (ret) +				goto err_release; +			data_left -= size; +			tso_build_data(skb, &tso, size); +		} +	} + +	__skb_queue_tail(&txq->tx_skb, skb); +	skb_tx_timestamp(skb); + +	/* clear TX_END status */ +	mp->work_tx_end &= ~(1 << txq->index); + +	/* ensure all descriptors are written before poking hardware */ +	wmb(); +	txq_enable(txq); +	txq->tx_desc_count += desc_count; +	return 0; +err_release: +	/* TODO: Release all used data descriptors; header descriptors must not +	 * be DMA-unmapped. +	 */ +	return ret; +} +  static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)  {  	struct mv643xx_eth_private *mp = txq_to_mp(txq); @@ -672,8 +879,10 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)  		skb_frag_t *this_frag;  		int tx_index;  		struct tx_desc *desc; +		void *addr;  		this_frag = &skb_shinfo(skb)->frags[frag]; +		addr = page_address(this_frag->page.p) + this_frag->page_offset;  		tx_index = txq->tx_curr_desc++;  		if (txq->tx_curr_desc == txq->tx_ring_size)  			txq->tx_curr_desc = 0; @@ -693,19 +902,13 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)  		desc->l4i_chk = 0;  		desc->byte_cnt = skb_frag_size(this_frag); -		desc->buf_ptr = skb_frag_dma_map(mp->dev->dev.parent, -						 this_frag, 0, -						 skb_frag_size(this_frag), -						 DMA_TO_DEVICE); +		desc->buf_ptr = dma_map_single(mp->dev->dev.parent, addr, +					       desc->byte_cnt, DMA_TO_DEVICE);  	}  } -static inline __be16 sum16_as_be(__sum16 sum) -{ -	return (__force __be16)sum; -} - -static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) +static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb, +			  struct net_device *dev)  {  	struct mv643xx_eth_private *mp = txq_to_mp(txq);  	int nr_frags = skb_shinfo(skb)->nr_frags; @@ -713,54 +916,22 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)  	struct tx_desc *desc;  	u32 cmd_sts;  	u16 l4i_chk; -	int length; +	int length, ret; -	cmd_sts = TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA; +	cmd_sts = 0;  	l4i_chk = 0; -	if (skb->ip_summed == CHECKSUM_PARTIAL) { -		int hdr_len; -		int tag_bytes; - -		BUG_ON(skb->protocol != htons(ETH_P_IP) && -		       skb->protocol != htons(ETH_P_8021Q)); - -		hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; -		tag_bytes = hdr_len - ETH_HLEN; -		if (skb->len - hdr_len > mp->shared->tx_csum_limit || -		    unlikely(tag_bytes & ~12)) { -			if (skb_checksum_help(skb) == 0) -				goto no_csum; -			kfree_skb(skb); -			return 1; -		} - -		if (tag_bytes & 4) -			cmd_sts |= MAC_HDR_EXTRA_4_BYTES; -		if (tag_bytes & 8) -			cmd_sts |= MAC_HDR_EXTRA_8_BYTES; - -		cmd_sts |= GEN_TCP_UDP_CHECKSUM | -			   GEN_IP_V4_CHECKSUM   | -			   ip_hdr(skb)->ihl << TX_IHL_SHIFT; - -		switch (ip_hdr(skb)->protocol) { -		case IPPROTO_UDP: -			cmd_sts |= UDP_FRAME; -			l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); -			break; -		case IPPROTO_TCP: -			l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); -			break; -		default: -			BUG(); -		} -	} else { -no_csum: -		/* Errata BTS #50, IHL must be 5 if no HW checksum */ -		cmd_sts |= 5 << TX_IHL_SHIFT; +	if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { +		if (net_ratelimit()) +			netdev_err(dev, "tx queue full?!\n"); +		return -EBUSY;  	} +	ret = skb_tx_csum(mp, skb, &l4i_chk, &cmd_sts, skb->len); +	if (ret) +		return ret; +	cmd_sts |= TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA; +  	tx_index = txq->tx_curr_desc++;  	if (txq->tx_curr_desc == txq->tx_ring_size)  		txq->tx_curr_desc = 0; @@ -802,7 +973,7 @@ no_csum:  static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)  {  	struct mv643xx_eth_private *mp = netdev_priv(dev); -	int length, queue; +	int length, queue, ret;  	struct tx_queue *txq;  	struct netdev_queue *nq; @@ -811,30 +982,26 @@ static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)  	nq = netdev_get_tx_queue(dev, queue);  	if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { -		txq->tx_dropped++;  		netdev_printk(KERN_DEBUG, dev,  			      "failed to linearize skb with tiny unaligned fragment\n");  		return NETDEV_TX_BUSY;  	} -	if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { -		if (net_ratelimit()) -			netdev_err(dev, "tx queue full?!\n"); -		kfree_skb(skb); -		return NETDEV_TX_OK; -	} -  	length = skb->len; -	if (!txq_submit_skb(txq, skb)) { -		int entries_left; - +	if (skb_is_gso(skb)) +		ret = txq_submit_tso(txq, skb, dev); +	else +		ret = txq_submit_skb(txq, skb, dev); +	if (!ret) {  		txq->tx_bytes += length;  		txq->tx_packets++; -		entries_left = txq->tx_ring_size - txq->tx_desc_count; -		if (entries_left < MAX_SKB_FRAGS + 1) +		if (txq->tx_desc_count >= txq->tx_stop_threshold)  			netif_tx_stop_queue(nq); +	} else { +		txq->tx_dropped++; +		dev_kfree_skb_any(skb);  	}  	return NETDEV_TX_OK; @@ -908,14 +1075,9 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)  			mp->dev->stats.tx_errors++;  		} -		if (cmd_sts & TX_FIRST_DESC) { +		if (!IS_TSO_HEADER(txq, desc->buf_ptr))  			dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,  					 desc->byte_cnt, DMA_TO_DEVICE); -		} else { -			dma_unmap_page(mp->dev->dev.parent, desc->buf_ptr, -				       desc->byte_cnt, DMA_TO_DEVICE); -		} -  		dev_kfree_skb(skb);  	} @@ -1011,8 +1173,9 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq)  /* mii management interface *************************************************/ -static void mv643xx_adjust_pscr(struct mv643xx_eth_private *mp) +static void mv643xx_eth_adjust_link(struct net_device *dev)  { +	struct mv643xx_eth_private *mp = netdev_priv(dev);  	u32 pscr = rdlp(mp, PORT_SERIAL_CONTROL);  	u32 autoneg_disable = FORCE_LINK_PASS |  	             DISABLE_AUTO_NEG_SPEED_GMII | @@ -1131,15 +1294,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)  	p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);  	p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);  	spin_unlock_bh(&mp->mib_counters_lock); - -	mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);  }  static void mib_counters_timer_wrapper(unsigned long _mp)  {  	struct mv643xx_eth_private *mp = (void *)_mp; -  	mib_counters_update(mp); +	mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);  } @@ -1390,7 +1551,7 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)  	ret = phy_ethtool_sset(mp->phy, cmd);  	if (!ret) -		mv643xx_adjust_pscr(mp); +		mv643xx_eth_adjust_link(dev);  	return ret;  } @@ -1459,7 +1620,11 @@ mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er)  		return -EINVAL;  	mp->rx_ring_size = er->rx_pending < 4096 ? er->rx_pending : 4096; -	mp->tx_ring_size = er->tx_pending < 4096 ? er->tx_pending : 4096; +	mp->tx_ring_size = clamp_t(unsigned int, er->tx_pending, +				   MV643XX_MAX_SKB_DESCS * 2, 4096); +	if (mp->tx_ring_size != er->tx_pending) +		netdev_warn(dev, "TX queue size set to %u (requested %u)\n", +			    mp->tx_ring_size, er->tx_pending);  	if (netif_running(dev)) {  		mv643xx_eth_stop(dev); @@ -1835,6 +2000,13 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)  	txq->tx_ring_size = mp->tx_ring_size; +	/* A queue must always have room for at least one skb. +	 * Therefore, stop the queue when the free entries reaches +	 * the maximum number of descriptors per skb. +	 */ +	txq->tx_stop_threshold = txq->tx_ring_size - MV643XX_MAX_SKB_DESCS; +	txq->tx_wake_threshold = txq->tx_stop_threshold / 2; +  	txq->tx_desc_count = 0;  	txq->tx_curr_desc = 0;  	txq->tx_used_desc = 0; @@ -1874,6 +2046,15 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)  					nexti * sizeof(struct tx_desc);  	} +	/* Allocate DMA buffers for TSO MAC/IP/TCP headers */ +	txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent, +					   txq->tx_ring_size * TSO_HEADER_SIZE, +					   &txq->tso_hdrs_dma, GFP_KERNEL); +	if (txq->tso_hdrs == NULL) { +		dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size, +				  txq->tx_desc_area, txq->tx_desc_dma); +		return -ENOMEM; +	}  	skb_queue_head_init(&txq->tx_skb);  	return 0; @@ -1894,6 +2075,10 @@ static void txq_deinit(struct tx_queue *txq)  	else  		dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,  				  txq->tx_desc_area, txq->tx_desc_dma); +	if (txq->tso_hdrs) +		dma_free_coherent(mp->dev->dev.parent, +				  txq->tx_ring_size * TSO_HEADER_SIZE, +				  txq->tso_hdrs, txq->tso_hdrs_dma);  } @@ -2069,23 +2254,6 @@ static inline void oom_timer_wrapper(unsigned long data)  	napi_schedule(&mp->napi);  } -static void phy_reset(struct mv643xx_eth_private *mp) -{ -	int data; - -	data = phy_read(mp->phy, MII_BMCR); -	if (data < 0) -		return; - -	data |= BMCR_RESET; -	if (phy_write(mp->phy, MII_BMCR, data) < 0) -		return; - -	do { -		data = phy_read(mp->phy, MII_BMCR); -	} while (data >= 0 && data & BMCR_RESET); -} -  static void port_start(struct mv643xx_eth_private *mp)  {  	u32 pscr; @@ -2098,8 +2266,9 @@ static void port_start(struct mv643xx_eth_private *mp)  		struct ethtool_cmd cmd;  		mv643xx_eth_get_settings(mp->dev, &cmd); -		phy_reset(mp); +		phy_init_hw(mp->phy);  		mv643xx_eth_set_settings(mp->dev, &cmd); +		phy_start(mp->phy);  	}  	/* @@ -2237,6 +2406,7 @@ static int mv643xx_eth_open(struct net_device *dev)  		mp->int_mask |= INT_TX_END_0 << i;  	} +	add_timer(&mp->mib_counters_timer);  	port_start(mp);  	wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); @@ -2294,7 +2464,8 @@ static int mv643xx_eth_stop(struct net_device *dev)  	del_timer_sync(&mp->rx_oom);  	netif_carrier_off(dev); - +	if (mp->phy) +		phy_stop(mp->phy);  	free_irq(dev->irq, dev);  	port_reset(mp); @@ -2320,7 +2491,7 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)  	ret = phy_mii_ioctl(mp->phy, ifr, cmd);  	if (!ret) -		mv643xx_adjust_pscr(mp); +		mv643xx_eth_adjust_link(dev);  	return ret;  } @@ -2514,7 +2685,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,  	mac_addr = of_get_mac_address(pnp);  	if (mac_addr) -		memcpy(ppd.mac_addr, mac_addr, 6); +		memcpy(ppd.mac_addr, mac_addr, ETH_ALEN);  	mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size);  	mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr); @@ -2534,6 +2705,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,  	if (!ppdev)  		return -ENOMEM;  	ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); +	ppdev->dev.of_node = pnp;  	ret = platform_device_add_resources(ppdev, &res, 1);  	if (ret) @@ -2694,9 +2866,10 @@ static void set_params(struct mv643xx_eth_private *mp,  		       struct mv643xx_eth_platform_data *pd)  {  	struct net_device *dev = mp->dev; +	unsigned int tx_ring_size;  	if (is_valid_ether_addr(pd->mac_addr)) -		memcpy(dev->dev_addr, pd->mac_addr, 6); +		memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);  	else  		uc_addr_get(mp, dev->dev_addr); @@ -2708,22 +2881,22 @@ static void set_params(struct mv643xx_eth_private *mp,  	mp->rxq_count = pd->rx_queue_count ? : 1; -	mp->tx_ring_size = DEFAULT_TX_QUEUE_SIZE; +	tx_ring_size = DEFAULT_TX_QUEUE_SIZE;  	if (pd->tx_queue_size) -		mp->tx_ring_size = pd->tx_queue_size; +		tx_ring_size = pd->tx_queue_size; + +	mp->tx_ring_size = clamp_t(unsigned int, tx_ring_size, +				   MV643XX_MAX_SKB_DESCS * 2, 4096); +	if (mp->tx_ring_size != tx_ring_size) +		netdev_warn(dev, "TX queue size set to %u (requested %u)\n", +			    mp->tx_ring_size, tx_ring_size); +  	mp->tx_desc_sram_addr = pd->tx_sram_addr;  	mp->tx_desc_sram_size = pd->tx_sram_size;  	mp->txq_count = pd->tx_queue_count ? : 1;  } -static void mv643xx_eth_adjust_link(struct net_device *dev) -{ -	struct mv643xx_eth_private *mp = netdev_priv(dev); - -	mv643xx_adjust_pscr(mp); -} -  static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,  				   int phy_addr)  { @@ -2764,8 +2937,6 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)  {  	struct phy_device *phy = mp->phy; -	phy_reset(mp); -  	if (speed == 0) {  		phy->autoneg = AUTONEG_ENABLE;  		phy->speed = 0; @@ -2890,6 +3061,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)  					 PHY_INTERFACE_MODE_GMII);  		if (!mp->phy)  			err = -ENODEV; +		else +			phy_addr_set(mp, mp->phy->addr);  	} else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {  		mp->phy = phy_scan(mp, pd->phy_addr); @@ -2905,7 +3078,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)  	if (err)  		goto out; -	SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); +	dev->ethtool_ops = &mv643xx_eth_ethtool_ops;  	init_pscr(mp, pd->speed, pd->duplex); @@ -2916,7 +3089,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)  	mp->mib_counters_timer.data = (unsigned long)mp;  	mp->mib_counters_timer.function = mib_counters_timer_wrapper;  	mp->mib_counters_timer.expires = jiffies + 30 * HZ; -	add_timer(&mp->mib_counters_timer);  	spin_lock_init(&mp->mib_counters_lock); @@ -2938,11 +3110,14 @@ static int mv643xx_eth_probe(struct platform_device *pdev)  	dev->watchdog_timeo = 2 * HZ;  	dev->base_addr = 0; -	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; -	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM; -	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM; +	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; +	dev->vlan_features = dev->features; + +	dev->features |= NETIF_F_RXCSUM; +	dev->hw_features = dev->features;  	dev->priv_flags |= IFF_UNICAST_FLT; +	dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;  	SET_NETDEV_DEV(dev, &pdev->dev); diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index e2f66266031..fc2fb25343f 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -4,11 +4,9 @@   * Since the MDIO interface of Marvell network interfaces is shared   * between all network interfaces, having a single driver allows to   * handle concurrent accesses properly (you may have four Ethernet - * ports, but they in fact share the same SMI interface to access the - * MDIO bus). Moreover, this MDIO interface code is similar between - * the mv643xx_eth driver and the mvneta driver. For now, it is only - * used by the mvneta driver, but it could later be used by the - * mv643xx_eth driver as well. + * ports, but they in fact share the same SMI interface to access + * the MDIO bus). This driver is currently used by the mvneta and + * mv643xx_eth drivers.   *   * Copyright (C) 2012 Marvell   * @@ -19,7 +17,6 @@   * warranty of any kind, whether express or implied.   */ -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/mutex.h> @@ -44,6 +41,15 @@  #define  MVMDIO_ERR_INT_SMI_DONE	   0x00000010  #define MVMDIO_ERR_INT_MASK		   0x0080 +/* + * SMI Timeout measurements: + * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt) + * - Armada 370       (Globalscale Mirabox):   41us to 43us (Polled) + */ +#define MVMDIO_SMI_TIMEOUT		   1000 /* 1000us = 1ms */ +#define MVMDIO_SMI_POLL_INTERVAL_MIN	   45 +#define MVMDIO_SMI_POLL_INTERVAL_MAX	   55 +  struct orion_mdio_dev {  	struct mutex lock;  	void __iomem *regs; @@ -68,77 +74,74 @@ static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)  static int orion_mdio_wait_ready(struct mii_bus *bus)  {  	struct orion_mdio_dev *dev = bus->priv; -	int count; - -	if (dev->err_interrupt <= 0) { -		count = 0; -		while (1) { -			if (orion_mdio_smi_is_done(dev)) -				break; - -			if (count > 100) { -				dev_err(bus->parent, -					"Timeout: SMI busy for too long\n"); -				return -ETIMEDOUT; -			} - -			udelay(10); -			count++; -		} -	} else { -		if (!orion_mdio_smi_is_done(dev)) { +	unsigned long timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT); +	unsigned long end = jiffies + timeout; +	int timedout = 0; + +	while (1) { +	        if (orion_mdio_smi_is_done(dev)) +			return 0; +	        else if (timedout) +			break; + +	        if (dev->err_interrupt <= 0) { +			usleep_range(MVMDIO_SMI_POLL_INTERVAL_MIN, +				     MVMDIO_SMI_POLL_INTERVAL_MAX); + +			if (time_is_before_jiffies(end)) +				++timedout; +	        } else { +			/* wait_event_timeout does not guarantee a delay of at +			 * least one whole jiffie, so timeout must be no less +			 * than two. +			 */ +			if (timeout < 2) +				timeout = 2;  			wait_event_timeout(dev->smi_busy_wait, -				orion_mdio_smi_is_done(dev), -				msecs_to_jiffies(100)); -			if (!orion_mdio_smi_is_done(dev)) -				return -ETIMEDOUT; -		} +				           orion_mdio_smi_is_done(dev), +				           timeout); + +			++timedout; +	        }  	} -	return 0; +	dev_err(bus->parent, "Timeout: SMI busy for too long\n"); +	return  -ETIMEDOUT;  }  static int orion_mdio_read(struct mii_bus *bus, int mii_id,  			   int regnum)  {  	struct orion_mdio_dev *dev = bus->priv; -	int count;  	u32 val;  	int ret;  	mutex_lock(&dev->lock);  	ret = orion_mdio_wait_ready(bus); -	if (ret < 0) { -		mutex_unlock(&dev->lock); -		return ret; -	} +	if (ret < 0) +		goto out;  	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |  		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |  		MVMDIO_SMI_READ_OPERATION),  	       dev->regs); -	/* Wait for the value to become available */ -	count = 0; -	while (1) { -		val = readl(dev->regs); -		if (val & MVMDIO_SMI_READ_VALID) -			break; - -		if (count > 100) { -			dev_err(bus->parent, "Timeout when reading PHY\n"); -			mutex_unlock(&dev->lock); -			return -ETIMEDOUT; -		} +	ret = orion_mdio_wait_ready(bus); +	if (ret < 0) +		goto out; -		udelay(10); -		count++; +	val = readl(dev->regs); +	if (!(val & MVMDIO_SMI_READ_VALID)) { +		dev_err(bus->parent, "SMI bus read not valid\n"); +		ret = -ENODEV; +		goto out;  	} +	ret = val & 0xFFFF; +out:  	mutex_unlock(&dev->lock); - -	return val & 0xFFFF; +	return ret;  }  static int orion_mdio_write(struct mii_bus *bus, int mii_id, @@ -150,10 +153,8 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,  	mutex_lock(&dev->lock);  	ret = orion_mdio_wait_ready(bus); -	if (ret < 0) { -		mutex_unlock(&dev->lock); -		return ret; -	} +	if (ret < 0) +		goto out;  	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |  		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  | @@ -161,14 +162,9 @@ static int orion_mdio_write(struct mii_bus *bus, int mii_id,  		(value << MVMDIO_SMI_DATA_SHIFT)),  	       dev->regs); +out:  	mutex_unlock(&dev->lock); - -	return 0; -} - -static int orion_mdio_reset(struct mii_bus *bus) -{ -	return 0; +	return ret;  }  static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id) @@ -199,25 +195,22 @@ static int orion_mdio_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev)); -	if (!bus) { -		dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); +	bus = devm_mdiobus_alloc_size(&pdev->dev, +				      sizeof(struct orion_mdio_dev)); +	if (!bus)  		return -ENOMEM; -	}  	bus->name = "orion_mdio_bus";  	bus->read = orion_mdio_read;  	bus->write = orion_mdio_write; -	bus->reset = orion_mdio_reset;  	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii",  		 dev_name(&pdev->dev));  	bus->parent = &pdev->dev; -	bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); -	if (!bus->irq) { -		mdiobus_free(bus); +	bus->irq = devm_kmalloc_array(&pdev->dev, PHY_MAX_ADDR, sizeof(int), +				      GFP_KERNEL); +	if (!bus->irq)  		return -ENOMEM; -	}  	for (i = 0; i < PHY_MAX_ADDR; i++)  		bus->irq[i] = PHY_POLL; @@ -237,7 +230,7 @@ static int orion_mdio_probe(struct platform_device *pdev)  		clk_prepare_enable(dev->clk);  	dev->err_interrupt = platform_get_irq(pdev, 0); -	if (dev->err_interrupt != -ENXIO) { +	if (dev->err_interrupt > 0) {  		ret = devm_request_irq(&pdev->dev, dev->err_interrupt,  					orion_mdio_err_irq,  					IRQF_SHARED, pdev->name, dev); @@ -246,6 +239,9 @@ static int orion_mdio_probe(struct platform_device *pdev)  		writel(MVMDIO_ERR_INT_SMI_DONE,  			dev->regs + MVMDIO_ERR_INT_MASK); + +	} else if (dev->err_interrupt == -EPROBE_DEFER) { +		return -EPROBE_DEFER;  	}  	mutex_init(&dev->lock); @@ -266,8 +262,6 @@ static int orion_mdio_probe(struct platform_device *pdev)  out_mdio:  	if (!IS_ERR(dev->clk))  		clk_disable_unprepare(dev->clk); -	kfree(bus->irq); -	mdiobus_free(bus);  	return ret;  } @@ -278,8 +272,6 @@ static int orion_mdio_remove(struct platform_device *pdev)  	writel(0, dev->regs + MVMDIO_ERR_INT_MASK);  	mdiobus_unregister(bus); -	kfree(bus->irq); -	mdiobus_free(bus);  	if (!IS_ERR(dev->clk))  		clk_disable_unprepare(dev->clk); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index e35bac7cfdf..dadd9a5f632 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -22,6 +22,8 @@  #include <linux/interrupt.h>  #include <net/ip.h>  #include <net/ipv6.h> +#include <linux/io.h> +#include <net/tso.h>  #include <linux/of.h>  #include <linux/of_irq.h>  #include <linux/of_mdio.h> @@ -88,8 +90,9 @@  #define      MVNETA_TX_IN_PRGRS                  BIT(1)  #define      MVNETA_TX_FIFO_EMPTY                BIT(8)  #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c -#define MVNETA_SGMII_SERDES_CFG			 0x24A0 +#define MVNETA_SERDES_CFG			 0x24A0  #define      MVNETA_SGMII_SERDES_PROTO		 0x0cc7 +#define      MVNETA_QSGMII_SERDES_PROTO		 0x0667  #define MVNETA_TYPE_PRIO                         0x24bc  #define      MVNETA_FORCE_UNI                    BIT(21)  #define MVNETA_TXQ_CMD_1                         0x24e4 @@ -101,16 +104,56 @@  #define      MVNETA_CPU_RXQ_ACCESS_ALL_MASK      0x000000ff  #define      MVNETA_CPU_TXQ_ACCESS_ALL_MASK      0x0000ff00  #define MVNETA_RXQ_TIME_COAL_REG(q)              (0x2580 + ((q) << 2)) + +/* Exception Interrupt Port/Queue Cause register */ +  #define MVNETA_INTR_NEW_CAUSE                    0x25a0 -#define      MVNETA_RX_INTR_MASK(nr_rxqs)        (((1 << nr_rxqs) - 1) << 8)  #define MVNETA_INTR_NEW_MASK                     0x25a4 + +/* bits  0..7  = TXQ SENT, one bit per queue. + * bits  8..15 = RXQ OCCUP, one bit per queue. + * bits 16..23 = RXQ FREE, one bit per queue. + * bit  29 = OLD_REG_SUM, see old reg ? + * bit  30 = TX_ERR_SUM, one bit for 4 ports + * bit  31 = MISC_SUM,   one bit for 4 ports + */ +#define      MVNETA_TX_INTR_MASK(nr_txqs)        (((1 << nr_txqs) - 1) << 0) +#define      MVNETA_TX_INTR_MASK_ALL             (0xff << 0) +#define      MVNETA_RX_INTR_MASK(nr_rxqs)        (((1 << nr_rxqs) - 1) << 8) +#define      MVNETA_RX_INTR_MASK_ALL             (0xff << 8) +  #define MVNETA_INTR_OLD_CAUSE                    0x25a8  #define MVNETA_INTR_OLD_MASK                     0x25ac + +/* Data Path Port/Queue Cause Register */  #define MVNETA_INTR_MISC_CAUSE                   0x25b0  #define MVNETA_INTR_MISC_MASK                    0x25b4 + +#define      MVNETA_CAUSE_PHY_STATUS_CHANGE      BIT(0) +#define      MVNETA_CAUSE_LINK_CHANGE            BIT(1) +#define      MVNETA_CAUSE_PTP                    BIT(4) + +#define      MVNETA_CAUSE_INTERNAL_ADDR_ERR      BIT(7) +#define      MVNETA_CAUSE_RX_OVERRUN             BIT(8) +#define      MVNETA_CAUSE_RX_CRC_ERROR           BIT(9) +#define      MVNETA_CAUSE_RX_LARGE_PKT           BIT(10) +#define      MVNETA_CAUSE_TX_UNDERUN             BIT(11) +#define      MVNETA_CAUSE_PRBS_ERR               BIT(12) +#define      MVNETA_CAUSE_PSC_SYNC_CHANGE        BIT(13) +#define      MVNETA_CAUSE_SERDES_SYNC_ERR        BIT(14) + +#define      MVNETA_CAUSE_BMU_ALLOC_ERR_SHIFT    16 +#define      MVNETA_CAUSE_BMU_ALLOC_ERR_ALL_MASK   (0xF << MVNETA_CAUSE_BMU_ALLOC_ERR_SHIFT) +#define      MVNETA_CAUSE_BMU_ALLOC_ERR_MASK(pool) (1 << (MVNETA_CAUSE_BMU_ALLOC_ERR_SHIFT + (pool))) + +#define      MVNETA_CAUSE_TXQ_ERROR_SHIFT        24 +#define      MVNETA_CAUSE_TXQ_ERROR_ALL_MASK     (0xFF << MVNETA_CAUSE_TXQ_ERROR_SHIFT) +#define      MVNETA_CAUSE_TXQ_ERROR_MASK(q)      (1 << (MVNETA_CAUSE_TXQ_ERROR_SHIFT + (q))) +  #define MVNETA_INTR_ENABLE                       0x25b8  #define      MVNETA_TXQ_INTR_ENABLE_ALL_MASK     0x0000ff00 -#define      MVNETA_RXQ_INTR_ENABLE_ALL_MASK     0xff000000 +#define      MVNETA_RXQ_INTR_ENABLE_ALL_MASK     0xff000000  // note: neta says it's 0x000000FF +  #define MVNETA_RXQ_CMD                           0x2680  #define      MVNETA_RXQ_DISABLE_SHIFT            8  #define      MVNETA_RXQ_ENABLE_MASK              0x000000ff @@ -121,7 +164,7 @@  #define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc  #define      MVNETA_GMAC0_PORT_ENABLE            BIT(0)  #define MVNETA_GMAC_CTRL_2                       0x2c08 -#define      MVNETA_GMAC2_PSC_ENABLE             BIT(3) +#define      MVNETA_GMAC2_PCS_ENABLE             BIT(3)  #define      MVNETA_GMAC2_PORT_RGMII             BIT(4)  #define      MVNETA_GMAC2_PORT_RESET             BIT(6)  #define MVNETA_GMAC_STATUS                       0x2c10 @@ -176,12 +219,6 @@  #define MVNETA_RX_COAL_PKTS		32  #define MVNETA_RX_COAL_USEC		100 -/* Timer */ -#define MVNETA_TX_DONE_TIMER_PERIOD	10 - -/* Napi polling weight */ -#define MVNETA_RX_POLL_WEIGHT		64 -  /* The two bytes Marvell header. Either contains a special value used   * by Marvell switches when a specific hardware mode is enabled (not   * supported by this driver) or is filled automatically by zeroes on @@ -205,12 +242,20 @@  #define MVNETA_TX_MTU_MAX		0x3ffff +/* TSO header size */ +#define TSO_HEADER_SIZE 128 +  /* Max number of Rx descriptors */  #define MVNETA_MAX_RXD 128  /* Max number of Tx descriptors */  #define MVNETA_MAX_TXD 532 +/* Max number of allowed TCP segments for software TSO */ +#define MVNETA_MAX_TSO_SEGS 100 + +#define MVNETA_MAX_SKB_DESCS (MVNETA_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) +  /* descriptor aligned size */  #define MVNETA_DESC_ALIGNED_SIZE	32 @@ -219,39 +264,37 @@  	      ETH_HLEN + ETH_FCS_LEN,			     \  	      MVNETA_CPU_D_CACHE_LINE_SIZE) +#define IS_TSO_HEADER(txq, addr) \ +	((addr >= txq->tso_hdrs_phys) && \ +	 (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE)) +  #define MVNETA_RX_BUF_SIZE(pkt_size)   ((pkt_size) + NET_SKB_PAD) -struct mvneta_stats { +struct mvneta_pcpu_stats {  	struct	u64_stats_sync syncp; -	u64	packets; -	u64	bytes; +	u64	rx_packets; +	u64	rx_bytes; +	u64	tx_packets; +	u64	tx_bytes;  };  struct mvneta_port {  	int pkt_size; +	unsigned int frag_size;  	void __iomem *base;  	struct mvneta_rx_queue *rxqs;  	struct mvneta_tx_queue *txqs; -	struct timer_list tx_done_timer;  	struct net_device *dev;  	u32 cause_rx_tx;  	struct napi_struct napi; -	/* Flags */ -	unsigned long flags; -#define MVNETA_F_TX_DONE_TIMER_BIT  0 - -	/* Napi weight */ -	int weight; -  	/* Core clock */  	struct clk *clk;  	u8 mcast_count[256];  	u16 tx_ring_size;  	u16 rx_ring_size; -	struct mvneta_stats tx_stats; -	struct mvneta_stats rx_stats; +	struct mvneta_pcpu_stats *stats;  	struct mii_bus *mii_bus;  	struct phy_device *phy_dev; @@ -354,6 +397,8 @@ struct mvneta_tx_queue {  	 * descriptor ring  	 */  	int count; +	int tx_stop_threshold; +	int tx_wake_threshold;  	/* Array of transmitted skb */  	struct sk_buff **tx_skb; @@ -377,6 +422,12 @@ struct mvneta_tx_queue {  	/* Index of the next TX DMA descriptor to process */  	int next_desc_to_proc; + +	/* DMA buffers for TSO headers */ +	char *tso_hdrs; + +	/* DMA address of TSO headers */ +	dma_addr_t tso_hdrs_phys;  };  struct mvneta_rx_queue { @@ -405,11 +456,16 @@ struct mvneta_rx_queue {  	int next_desc_to_proc;  }; -static int rxq_number = 8; +/* The hardware supports eight (8) rx queues, but we are only allowing + * the first one to be used. Therefore, let's just allocate one queue. + */ +static int rxq_number = 1;  static int txq_number = 8;  static int rxq_def; +static int rx_copybreak __read_mostly = 256; +  #define MVNETA_DRIVER_NAME "mvneta"  #define MVNETA_DRIVER_VERSION "1.0" @@ -461,21 +517,29 @@ struct rtnl_link_stats64 *mvneta_get_stats64(struct net_device *dev,  {  	struct mvneta_port *pp = netdev_priv(dev);  	unsigned int start; +	int cpu; -	memset(stats, 0, sizeof(struct rtnl_link_stats64)); - -	do { -		start = u64_stats_fetch_begin_bh(&pp->rx_stats.syncp); -		stats->rx_packets = pp->rx_stats.packets; -		stats->rx_bytes	= pp->rx_stats.bytes; -	} while (u64_stats_fetch_retry_bh(&pp->rx_stats.syncp, start)); +	for_each_possible_cpu(cpu) { +		struct mvneta_pcpu_stats *cpu_stats; +		u64 rx_packets; +		u64 rx_bytes; +		u64 tx_packets; +		u64 tx_bytes; +		cpu_stats = per_cpu_ptr(pp->stats, cpu); +		do { +			start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); +			rx_packets = cpu_stats->rx_packets; +			rx_bytes   = cpu_stats->rx_bytes; +			tx_packets = cpu_stats->tx_packets; +			tx_bytes   = cpu_stats->tx_bytes; +		} while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -	do { -		start = u64_stats_fetch_begin_bh(&pp->tx_stats.syncp); -		stats->tx_packets = pp->tx_stats.packets; -		stats->tx_bytes	= pp->tx_stats.bytes; -	} while (u64_stats_fetch_retry_bh(&pp->tx_stats.syncp, start)); +		stats->rx_packets += rx_packets; +		stats->rx_bytes   += rx_bytes; +		stats->tx_packets += tx_packets; +		stats->tx_bytes   += tx_bytes; +	}  	stats->rx_errors	= dev->stats.rx_errors;  	stats->rx_dropped	= dev->stats.rx_dropped; @@ -487,14 +551,14 @@ struct rtnl_link_stats64 *mvneta_get_stats64(struct net_device *dev,  /* Rx descriptors helper methods */ -/* Checks whether the given RX descriptor is both the first and the - * last descriptor for the RX packet. Each RX packet is currently +/* Checks whether the RX descriptor having this status is both the first + * and the last descriptor for the RX packet. Each RX packet is currently   * received through a single RX descriptor, so not having each RX   * descriptor with its first and last bits set is an error   */ -static int mvneta_rxq_desc_is_first_last(struct mvneta_rx_desc *desc) +static int mvneta_rxq_desc_is_first_last(u32 status)  { -	return (desc->status & MVNETA_RXD_FIRST_LAST_DESC) == +	return (status & MVNETA_RXD_FIRST_LAST_DESC) ==  		MVNETA_RXD_FIRST_LAST_DESC;  } @@ -570,6 +634,7 @@ mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq)  	int rx_desc = rxq->next_desc_to_proc;  	rxq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc); +	prefetch(rxq->descs + rxq->next_desc_to_proc);  	return rxq->descs + rx_desc;  } @@ -665,35 +730,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp,  	mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);  } - - -/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */ -static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable) -{ -	u32  val; - -	val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - -	if (enable) -		val |= MVNETA_GMAC2_PORT_RGMII; -	else -		val &= ~MVNETA_GMAC2_PORT_RGMII; - -	mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); -} - -/* Config SGMII port */ -static void mvneta_port_sgmii_config(struct mvneta_port *pp) -{ -	u32 val; - -	val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); -	val |= MVNETA_GMAC2_PSC_ENABLE; -	mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); - -	mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); -} -  /* Start the Ethernet port RX and TX activity */  static void mvneta_port_up(struct mvneta_port *pp)  { @@ -1100,17 +1136,6 @@ static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp,  	txq->done_pkts_coal = value;  } -/* Trigger tx done timer in MVNETA_TX_DONE_TIMER_PERIOD msecs */ -static void mvneta_add_tx_done_timer(struct mvneta_port *pp) -{ -	if (test_and_set_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags) == 0) { -		pp->tx_done_timer.expires = jiffies + -			msecs_to_jiffies(MVNETA_TX_DONE_TIMER_PERIOD); -		add_timer(&pp->tx_done_timer); -	} -} - -  /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */  static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,  				u32 phys_addr, u32 cookie) @@ -1182,7 +1207,7 @@ static u32 mvneta_txq_desc_csum(int l3_offs, int l3_proto,  	command =  l3_offs    << MVNETA_TX_L3_OFF_SHIFT;  	command |= ip_hdr_len << MVNETA_TX_IP_HLEN_SHIFT; -	if (l3_proto == swab16(ETH_P_IP)) +	if (l3_proto == htons(ETH_P_IP))  		command |= MVNETA_TXD_IP_CSUM;  	else  		command |= MVNETA_TX_L3_IP6; @@ -1204,10 +1229,10 @@ static void mvneta_rx_error(struct mvneta_port *pp,  {  	u32 status = rx_desc->status; -	if (!mvneta_rxq_desc_is_first_last(rx_desc)) { +	if (!mvneta_rxq_desc_is_first_last(status)) {  		netdev_err(pp->dev,  			   "bad rx status %08x (buffer oversize), size=%d\n", -			   rx_desc->status, rx_desc->data_size); +			   status, rx_desc->data_size);  		return;  	} @@ -1231,13 +1256,12 @@ static void mvneta_rx_error(struct mvneta_port *pp,  	}  } -/* Handle RX checksum offload */ -static void mvneta_rx_csum(struct mvneta_port *pp, -			   struct mvneta_rx_desc *rx_desc, +/* Handle RX checksum offload based on the descriptor's status */ +static void mvneta_rx_csum(struct mvneta_port *pp, u32 status,  			   struct sk_buff *skb)  { -	if ((rx_desc->status & MVNETA_RXD_L3_IP4) && -	    (rx_desc->status & MVNETA_RXD_L4_CSUM_OK)) { +	if ((status & MVNETA_RXD_L3_IP4) && +	    (status & MVNETA_RXD_L4_CSUM_OK)) {  		skb->csum = 0;  		skb->ip_summed = CHECKSUM_UNNECESSARY;  		return; @@ -1246,13 +1270,16 @@ static void mvneta_rx_csum(struct mvneta_port *pp,  	skb->ip_summed = CHECKSUM_NONE;  } -/* Return tx queue pointer (find last set bit) according to causeTxDone reg */ +/* Return tx queue pointer (find last set bit) according to <cause> returned + * form tx_done reg. <cause> must not be null. The return value is always a + * valid queue for matching the first one found in <cause>. + */  static struct mvneta_tx_queue *mvneta_tx_done_policy(struct mvneta_port *pp,  						     u32 cause)  {  	int queue = fls(cause) - 1; -	return (queue < 0 || queue >= txq_number) ? NULL : &pp->txqs[queue]; +	return &pp->txqs[queue];  }  /* Free tx queue skbuffs */ @@ -1268,35 +1295,51 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,  		mvneta_txq_inc_get(txq); +		if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr)) +			dma_unmap_single(pp->dev->dev.parent, +					 tx_desc->buf_phys_addr, +					 tx_desc->data_size, DMA_TO_DEVICE);  		if (!skb)  			continue; - -		dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr, -				 tx_desc->data_size, DMA_TO_DEVICE);  		dev_kfree_skb_any(skb);  	}  }  /* Handle end of transmission */ -static int mvneta_txq_done(struct mvneta_port *pp, +static void mvneta_txq_done(struct mvneta_port *pp,  			   struct mvneta_tx_queue *txq)  {  	struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);  	int tx_done;  	tx_done = mvneta_txq_sent_desc_proc(pp, txq); -	if (tx_done == 0) -		return tx_done; +	if (!tx_done) +		return; +  	mvneta_txq_bufs_free(pp, txq, tx_done);  	txq->count -= tx_done;  	if (netif_tx_queue_stopped(nq)) { -		if (txq->size - txq->count >= MAX_SKB_FRAGS + 1) +		if (txq->count <= txq->tx_wake_threshold)  			netif_tx_wake_queue(nq);  	} +} + +static void *mvneta_frag_alloc(const struct mvneta_port *pp) +{ +	if (likely(pp->frag_size <= PAGE_SIZE)) +		return netdev_alloc_frag(pp->frag_size); +	else +		return kmalloc(pp->frag_size, GFP_ATOMIC); +} -	return tx_done; +static void mvneta_frag_free(const struct mvneta_port *pp, void *data) +{ +	if (likely(pp->frag_size <= PAGE_SIZE)) +		put_page(virt_to_head_page(data)); +	else +		kfree(data);  }  /* Refill processing */ @@ -1305,22 +1348,21 @@ static int mvneta_rx_refill(struct mvneta_port *pp,  {  	dma_addr_t phys_addr; -	struct sk_buff *skb; +	void *data; -	skb = netdev_alloc_skb(pp->dev, pp->pkt_size); -	if (!skb) +	data = mvneta_frag_alloc(pp); +	if (!data)  		return -ENOMEM; -	phys_addr = dma_map_single(pp->dev->dev.parent, skb->head, +	phys_addr = dma_map_single(pp->dev->dev.parent, data,  				   MVNETA_RX_BUF_SIZE(pp->pkt_size),  				   DMA_FROM_DEVICE);  	if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) { -		dev_kfree_skb(skb); +		mvneta_frag_free(pp, data);  		return -ENOMEM;  	} -	mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb); - +	mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);  	return 0;  } @@ -1374,11 +1416,11 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,  	rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);  	for (i = 0; i < rxq->size; i++) {  		struct mvneta_rx_desc *rx_desc = rxq->descs + i; -		struct sk_buff *skb = (struct sk_buff *)rx_desc->buf_cookie; +		void *data = (void *)rx_desc->buf_cookie; -		dev_kfree_skb_any(skb); +		mvneta_frag_free(pp, data);  		dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, -				 rx_desc->data_size, DMA_FROM_DEVICE); +				 MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);  	}  	if (rx_done) @@ -1391,6 +1433,8 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,  {  	struct net_device *dev = pp->dev;  	int rx_done, rx_filled; +	u32 rcvd_pkts = 0; +	u32 rcvd_bytes = 0;  	/* Get number of received packets */  	rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq); @@ -1405,67 +1449,223 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,  	while (rx_done < rx_todo) {  		struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);  		struct sk_buff *skb; +		unsigned char *data;  		u32 rx_status;  		int rx_bytes, err; -		prefetch(rx_desc);  		rx_done++;  		rx_filled++;  		rx_status = rx_desc->status; -		skb = (struct sk_buff *)rx_desc->buf_cookie; +		rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE); +		data = (unsigned char *)rx_desc->buf_cookie; -		if (!mvneta_rxq_desc_is_first_last(rx_desc) || +		if (!mvneta_rxq_desc_is_first_last(rx_status) ||  		    (rx_status & MVNETA_RXD_ERR_SUMMARY)) { +		err_drop_frame:  			dev->stats.rx_errors++;  			mvneta_rx_error(pp, rx_desc); -			mvneta_rx_desc_fill(rx_desc, rx_desc->buf_phys_addr, -					    (u32)skb); +			/* leave the descriptor untouched */  			continue;  		} -		dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, -				 rx_desc->data_size, DMA_FROM_DEVICE); +		if (rx_bytes <= rx_copybreak) { +			/* better copy a small frame and not unmap the DMA region */ +			skb = netdev_alloc_skb_ip_align(dev, rx_bytes); +			if (unlikely(!skb)) +				goto err_drop_frame; + +			dma_sync_single_range_for_cpu(dev->dev.parent, +			                              rx_desc->buf_phys_addr, +			                              MVNETA_MH_SIZE + NET_SKB_PAD, +			                              rx_bytes, +			                              DMA_FROM_DEVICE); +			memcpy(skb_put(skb, rx_bytes), +			       data + MVNETA_MH_SIZE + NET_SKB_PAD, +			       rx_bytes); + +			skb->protocol = eth_type_trans(skb, dev); +			mvneta_rx_csum(pp, rx_status, skb); +			napi_gro_receive(&pp->napi, skb); + +			rcvd_pkts++; +			rcvd_bytes += rx_bytes; + +			/* leave the descriptor and buffer untouched */ +			continue; +		} + +		skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size); +		if (!skb) +			goto err_drop_frame; + +		dma_unmap_single(dev->dev.parent, rx_desc->buf_phys_addr, +				 MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE); -		rx_bytes = rx_desc->data_size - -			(ETH_FCS_LEN + MVNETA_MH_SIZE); -		u64_stats_update_begin(&pp->rx_stats.syncp); -		pp->rx_stats.packets++; -		pp->rx_stats.bytes += rx_bytes; -		u64_stats_update_end(&pp->rx_stats.syncp); +		rcvd_pkts++; +		rcvd_bytes += rx_bytes;  		/* Linux processing */ -		skb_reserve(skb, MVNETA_MH_SIZE); +		skb_reserve(skb, MVNETA_MH_SIZE + NET_SKB_PAD);  		skb_put(skb, rx_bytes);  		skb->protocol = eth_type_trans(skb, dev); -		mvneta_rx_csum(pp, rx_desc, skb); +		mvneta_rx_csum(pp, rx_status, skb);  		napi_gro_receive(&pp->napi, skb);  		/* Refill processing */  		err = mvneta_rx_refill(pp, rx_desc);  		if (err) { -			netdev_err(pp->dev, "Linux processing - Can't refill\n"); +			netdev_err(dev, "Linux processing - Can't refill\n");  			rxq->missed++;  			rx_filled--;  		}  	} +	if (rcvd_pkts) { +		struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats); + +		u64_stats_update_begin(&stats->syncp); +		stats->rx_packets += rcvd_pkts; +		stats->rx_bytes   += rcvd_bytes; +		u64_stats_update_end(&stats->syncp); +	} +  	/* Update rxq management counters */  	mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled);  	return rx_done;  } +static inline void +mvneta_tso_put_hdr(struct sk_buff *skb, +		   struct mvneta_port *pp, struct mvneta_tx_queue *txq) +{ +	struct mvneta_tx_desc *tx_desc; +	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + +	txq->tx_skb[txq->txq_put_index] = NULL; +	tx_desc = mvneta_txq_next_desc_get(txq); +	tx_desc->data_size = hdr_len; +	tx_desc->command = mvneta_skb_tx_csum(pp, skb); +	tx_desc->command |= MVNETA_TXD_F_DESC; +	tx_desc->buf_phys_addr = txq->tso_hdrs_phys + +				 txq->txq_put_index * TSO_HEADER_SIZE; +	mvneta_txq_inc_put(txq); +} + +static inline int +mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq, +		    struct sk_buff *skb, char *data, int size, +		    bool last_tcp, bool is_last) +{ +	struct mvneta_tx_desc *tx_desc; + +	tx_desc = mvneta_txq_next_desc_get(txq); +	tx_desc->data_size = size; +	tx_desc->buf_phys_addr = dma_map_single(dev->dev.parent, data, +						size, DMA_TO_DEVICE); +	if (unlikely(dma_mapping_error(dev->dev.parent, +		     tx_desc->buf_phys_addr))) { +		mvneta_txq_desc_put(txq); +		return -ENOMEM; +	} + +	tx_desc->command = 0; +	txq->tx_skb[txq->txq_put_index] = NULL; + +	if (last_tcp) { +		/* last descriptor in the TCP packet */ +		tx_desc->command = MVNETA_TXD_L_DESC; + +		/* last descriptor in SKB */ +		if (is_last) +			txq->tx_skb[txq->txq_put_index] = skb; +	} +	mvneta_txq_inc_put(txq); +	return 0; +} + +static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev, +			 struct mvneta_tx_queue *txq) +{ +	int total_len, data_left; +	int desc_count = 0; +	struct mvneta_port *pp = netdev_priv(dev); +	struct tso_t tso; +	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); +	int i; + +	/* Count needed descriptors */ +	if ((txq->count + tso_count_descs(skb)) >= txq->size) +		return 0; + +	if (skb_headlen(skb) < (skb_transport_offset(skb) + tcp_hdrlen(skb))) { +		pr_info("*** Is this even  possible???!?!?\n"); +		return 0; +	} + +	/* 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; + +		data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); +		total_len -= data_left; +		desc_count++; + +		/* prepare packet headers: MAC + IP + TCP */ +		hdr = txq->tso_hdrs + txq->txq_put_index * TSO_HEADER_SIZE; +		tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); + +		mvneta_tso_put_hdr(skb, pp, txq); + +		while (data_left > 0) { +			int size; +			desc_count++; + +			size = min_t(int, tso.size, data_left); + +			if (mvneta_tso_put_data(dev, txq, skb, +						 tso.data, size, +						 size == data_left, +						 total_len == 0)) +				goto err_release; +			data_left -= size; + +			tso_build_data(skb, &tso, size); +		} +	} + +	return desc_count; + +err_release: +	/* Release all used data descriptors; header descriptors must not +	 * be DMA-unmapped. +	 */ +	for (i = desc_count - 1; i >= 0; i--) { +		struct mvneta_tx_desc *tx_desc = txq->descs + i; +		if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr)) +			dma_unmap_single(pp->dev->dev.parent, +					 tx_desc->buf_phys_addr, +					 tx_desc->data_size, +					 DMA_TO_DEVICE); +		mvneta_txq_desc_put(txq); +	} +	return 0; +} +  /* Handle tx fragmentation processing */  static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,  				  struct mvneta_tx_queue *txq)  {  	struct mvneta_tx_desc *tx_desc; -	int i; +	int i, nr_frags = skb_shinfo(skb)->nr_frags; -	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { +	for (i = 0; i < nr_frags; i++) {  		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];  		void *addr = page_address(frag->page.p) + frag->page_offset; @@ -1482,20 +1682,16 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,  			goto error;  		} -		if (i == (skb_shinfo(skb)->nr_frags - 1)) { +		if (i == nr_frags - 1) {  			/* Last descriptor */  			tx_desc->command = MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD; -  			txq->tx_skb[txq->txq_put_index] = skb; - -			mvneta_txq_inc_put(txq);  		} else {  			/* Descriptor in the middle: Not First, Not Last */  			tx_desc->command = 0; -  			txq->tx_skb[txq->txq_put_index] = NULL; -			mvneta_txq_inc_put(txq);  		} +		mvneta_txq_inc_put(txq);  	}  	return 0; @@ -1523,15 +1719,18 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)  	u16 txq_id = skb_get_queue_mapping(skb);  	struct mvneta_tx_queue *txq = &pp->txqs[txq_id];  	struct mvneta_tx_desc *tx_desc; -	struct netdev_queue *nq;  	int frags = 0;  	u32 tx_cmd;  	if (!netif_running(dev))  		goto out; +	if (skb_is_gso(skb)) { +		frags = mvneta_tx_tso(skb, dev, txq); +		goto out; +	} +  	frags = skb_shinfo(skb)->nr_frags + 1; -	nq    = netdev_get_tx_queue(dev, txq_id);  	/* Get a descriptor for the first part of the packet */  	tx_desc = mvneta_txq_next_desc_get(txq); @@ -1574,33 +1773,26 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)  		}  	} -	txq->count += frags; -	mvneta_txq_pend_desc_add(pp, txq, frags); - -	if (txq->size - txq->count < MAX_SKB_FRAGS + 1) -		netif_tx_stop_queue(nq); -  out:  	if (frags > 0) { -		u64_stats_update_begin(&pp->tx_stats.syncp); -		pp->tx_stats.packets++; -		pp->tx_stats.bytes += skb->len; -		u64_stats_update_end(&pp->tx_stats.syncp); +		struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats); +		struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id); + +		txq->count += frags; +		mvneta_txq_pend_desc_add(pp, txq, frags); + +		if (txq->count >= txq->tx_stop_threshold) +			netif_tx_stop_queue(nq); +		u64_stats_update_begin(&stats->syncp); +		stats->tx_packets++; +		stats->tx_bytes  += skb->len; +		u64_stats_update_end(&stats->syncp);  	} else {  		dev->stats.tx_dropped++;  		dev_kfree_skb_any(skb);  	} -	if (txq->count >= MVNETA_TXDONE_COAL_PKTS) -		mvneta_txq_done(pp, txq); - -	/* If after calling mvneta_txq_done, count equals -	 * frags, we need to set the timer -	 */ -	if (txq->count == frags && frags > 0) -		mvneta_add_tx_done_timer(pp); -  	return NETDEV_TX_OK;  } @@ -1620,33 +1812,26 @@ static void mvneta_txq_done_force(struct mvneta_port *pp,  	txq->txq_get_index = 0;  } -/* handle tx done - called from tx done timer callback */ -static u32 mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done, -			      int *tx_todo) +/* Handle tx done - called in softirq context. The <cause_tx_done> argument + * must be a valid cause according to MVNETA_TXQ_INTR_MASK_ALL. + */ +static void mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done)  {  	struct mvneta_tx_queue *txq; -	u32 tx_done = 0;  	struct netdev_queue *nq; -	*tx_todo = 0; -	while (cause_tx_done != 0) { +	while (cause_tx_done) {  		txq = mvneta_tx_done_policy(pp, cause_tx_done); -		if (!txq) -			break;  		nq = netdev_get_tx_queue(pp->dev, txq->id);  		__netif_tx_lock(nq, smp_processor_id()); -		if (txq->count) { -			tx_done += mvneta_txq_done(pp, txq); -			*tx_todo += txq->count; -		} +		if (txq->count) +			mvneta_txq_done(pp, txq);  		__netif_tx_unlock(nq);  		cause_tx_done &= ~((1 << txq->id));  	} - -	return tx_done;  }  /* Compute crc8 of the specified address, using a unique algorithm , @@ -1876,14 +2061,20 @@ static int mvneta_poll(struct napi_struct *napi, int budget)  	/* Read cause register */  	cause_rx_tx = mvreg_read(pp, MVNETA_INTR_NEW_CAUSE) & -		MVNETA_RX_INTR_MASK(rxq_number); +		(MVNETA_RX_INTR_MASK(rxq_number) | MVNETA_TX_INTR_MASK(txq_number)); + +	/* Release Tx descriptors */ +	if (cause_rx_tx & MVNETA_TX_INTR_MASK_ALL) { +		mvneta_tx_done_gbe(pp, (cause_rx_tx & MVNETA_TX_INTR_MASK_ALL)); +		cause_rx_tx &= ~MVNETA_TX_INTR_MASK_ALL; +	}  	/* For the case where the last mvneta_poll did not process all  	 * RX packets  	 */  	cause_rx_tx |= pp->cause_rx_tx;  	if (rxq_number > 1) { -		while ((cause_rx_tx != 0) && (budget > 0)) { +		while ((cause_rx_tx & MVNETA_RX_INTR_MASK_ALL) && (budget > 0)) {  			int count;  			struct mvneta_rx_queue *rxq;  			/* get rx queue number from cause_rx_tx */ @@ -1915,7 +2106,7 @@ static int mvneta_poll(struct napi_struct *napi, int budget)  		napi_complete(napi);  		local_irq_save(flags);  		mvreg_write(pp, MVNETA_INTR_NEW_MASK, -			    MVNETA_RX_INTR_MASK(rxq_number)); +			    MVNETA_RX_INTR_MASK(rxq_number) | MVNETA_TX_INTR_MASK(txq_number));  		local_irq_restore(flags);  	} @@ -1923,56 +2114,19 @@ static int mvneta_poll(struct napi_struct *napi, int budget)  	return rx_done;  } -/* tx done timer callback */ -static void mvneta_tx_done_timer_callback(unsigned long data) -{ -	struct net_device *dev = (struct net_device *)data; -	struct mvneta_port *pp = netdev_priv(dev); -	int tx_done = 0, tx_todo = 0; - -	if (!netif_running(dev)) -		return ; - -	clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); - -	tx_done = mvneta_tx_done_gbe(pp, -				     (((1 << txq_number) - 1) & -				      MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK), -				     &tx_todo); -	if (tx_todo > 0) -		mvneta_add_tx_done_timer(pp); -} -  /* Handle rxq fill: allocates rxq skbs; called when initializing a port */  static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,  			   int num)  { -	struct net_device *dev = pp->dev;  	int i;  	for (i = 0; i < num; i++) { -		struct sk_buff *skb; -		struct mvneta_rx_desc *rx_desc; -		unsigned long phys_addr; - -		skb = dev_alloc_skb(pp->pkt_size); -		if (!skb) { -			netdev_err(dev, "%s:rxq %d, %d of %d buffs  filled\n", +		memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc)); +		if (mvneta_rx_refill(pp, rxq->descs + i) != 0) { +			netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs  filled\n",  				__func__, rxq->id, i, num);  			break;  		} - -		rx_desc = rxq->descs + i; -		memset(rx_desc, 0, sizeof(struct mvneta_rx_desc)); -		phys_addr = dma_map_single(dev->dev.parent, skb->head, -					   MVNETA_RX_BUF_SIZE(pp->pkt_size), -					   DMA_FROM_DEVICE); -		if (unlikely(dma_mapping_error(dev->dev.parent, phys_addr))) { -			dev_kfree_skb(skb); -			break; -		} - -		mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb);  	}  	/* Add this number of RX descriptors as non occupied (ready to @@ -1988,7 +2142,7 @@ static void mvneta_tx_reset(struct mvneta_port *pp)  {  	int queue; -	/* free the skb's in the hal tx ring */ +	/* free the skb's in the tx ring */  	for (queue = 0; queue < txq_number; queue++)  		mvneta_txq_done_force(pp, &pp->txqs[queue]); @@ -2066,6 +2220,14 @@ static int mvneta_txq_init(struct mvneta_port *pp,  {  	txq->size = pp->tx_ring_size; +	/* A queue must always have room for at least one skb. +	 * Therefore, stop the queue when the free entries reaches +	 * the maximum number of descriptors per skb. +	 */ +	txq->tx_stop_threshold = txq->size - MVNETA_MAX_SKB_DESCS; +	txq->tx_wake_threshold = txq->tx_stop_threshold / 2; + +  	/* Allocate memory for TX descriptors */  	txq->descs = dma_alloc_coherent(pp->dev->dev.parent,  					txq->size * MVNETA_DESC_ALIGNED_SIZE, @@ -2094,6 +2256,18 @@ static int mvneta_txq_init(struct mvneta_port *pp,  				  txq->descs, txq->descs_phys);  		return -ENOMEM;  	} + +	/* Allocate DMA buffers for TSO MAC/IP/TCP headers */ +	txq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent, +					   txq->size * TSO_HEADER_SIZE, +					   &txq->tso_hdrs_phys, GFP_KERNEL); +	if (txq->tso_hdrs == NULL) { +		kfree(txq->tx_skb); +		dma_free_coherent(pp->dev->dev.parent, +				  txq->size * MVNETA_DESC_ALIGNED_SIZE, +				  txq->descs, txq->descs_phys); +		return -ENOMEM; +	}  	mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal);  	return 0; @@ -2105,6 +2279,10 @@ static void mvneta_txq_deinit(struct mvneta_port *pp,  {  	kfree(txq->tx_skb); +	if (txq->tso_hdrs) +		dma_free_coherent(pp->dev->dev.parent, +				  txq->size * TSO_HEADER_SIZE, +				  txq->tso_hdrs, txq->tso_hdrs_phys);  	if (txq->descs)  		dma_free_coherent(pp->dev->dev.parent,  				  txq->size * MVNETA_DESC_ALIGNED_SIZE, @@ -2192,7 +2370,7 @@ static void mvneta_start_dev(struct mvneta_port *pp)  	/* Unmask interrupts */  	mvreg_write(pp, MVNETA_INTR_NEW_MASK, -		    MVNETA_RX_INTR_MASK(rxq_number)); +		    MVNETA_RX_INTR_MASK(rxq_number) | MVNETA_TX_INTR_MASK(txq_number));  	phy_start(pp->phy_dev);  	netif_tx_start_all_queues(pp->dev); @@ -2225,16 +2403,6 @@ static void mvneta_stop_dev(struct mvneta_port *pp)  	mvneta_rx_reset(pp);  } -/* tx timeout callback - display a message and stop/start the network device */ -static void mvneta_tx_timeout(struct net_device *dev) -{ -	struct mvneta_port *pp = netdev_priv(dev); - -	netdev_info(dev, "tx timeout\n"); -	mvneta_stop_dev(pp); -	mvneta_start_dev(pp); -} -  /* Return positive if MTU is valid */  static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)  { @@ -2274,22 +2442,28 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)  		return 0;  	/* The interface is running, so we have to force a -	 * reallocation of the RXQs +	 * reallocation of the queues  	 */  	mvneta_stop_dev(pp);  	mvneta_cleanup_txqs(pp);  	mvneta_cleanup_rxqs(pp); -	pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); +	pp->pkt_size = MVNETA_RX_PKT_SIZE(dev->mtu); +	pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) + +	                SKB_DATA_ALIGN(sizeof(struct skb_shared_info));  	ret = mvneta_setup_rxqs(pp);  	if (ret) { -		netdev_err(pp->dev, "unable to setup rxqs after MTU change\n"); +		netdev_err(dev, "unable to setup rxqs after MTU change\n");  		return ret;  	} -	mvneta_setup_txqs(pp); +	ret = mvneta_setup_txqs(pp); +	if (ret) { +		netdev_err(dev, "unable to setup txqs after MTU change\n"); +		return ret; +	}  	mvneta_start_dev(pp);  	mvneta_port_up(pp); @@ -2316,22 +2490,19 @@ static void mvneta_get_mac_addr(struct mvneta_port *pp, unsigned char *addr)  static int mvneta_set_mac_addr(struct net_device *dev, void *addr)  {  	struct mvneta_port *pp = netdev_priv(dev); -	u8 *mac = addr + 2; -	int i; - -	if (netif_running(dev)) -		return -EBUSY; +	struct sockaddr *sockaddr = addr; +	int ret; +	ret = eth_prepare_mac_addr_change(dev, addr); +	if (ret < 0) +		return ret;  	/* Remove previous address table entry */  	mvneta_mac_addr_set(pp, dev->dev_addr, -1);  	/* Set new addr in hw */ -	mvneta_mac_addr_set(pp, mac, rxq_def); - -	/* Set addr in the device */ -	for (i = 0; i < ETH_ALEN; i++) -		dev->dev_addr[i] = mac[i]; +	mvneta_mac_addr_set(pp, sockaddr->sa_data, rxq_def); +	eth_commit_mac_addr_change(dev, addr);  	return 0;  } @@ -2358,7 +2529,7 @@ static void mvneta_adjust_link(struct net_device *ndev)  			if (phydev->speed == SPEED_1000)  				val |= MVNETA_GMAC_CONFIG_GMII_SPEED; -			else +			else if (phydev->speed == SPEED_100)  				val |= MVNETA_GMAC_CONFIG_MII_SPEED;  			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); @@ -2426,9 +2597,9 @@ static int mvneta_open(struct net_device *dev)  	struct mvneta_port *pp = netdev_priv(dev);  	int ret; -	mvneta_mac_addr_set(pp, dev->dev_addr, rxq_def); -  	pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); +	pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) + +	                SKB_DATA_ALIGN(sizeof(struct skb_shared_info));  	ret = mvneta_setup_rxqs(pp);  	if (ret) @@ -2478,8 +2649,6 @@ static int mvneta_stop(struct net_device *dev)  	free_irq(dev->irq, pp);  	mvneta_cleanup_rxqs(pp);  	mvneta_cleanup_txqs(pp); -	del_timer(&pp->tx_done_timer); -	clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags);  	return 0;  } @@ -2593,8 +2762,12 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev,  		return -EINVAL;  	pp->rx_ring_size = ring->rx_pending < MVNETA_MAX_RXD ?  		ring->rx_pending : MVNETA_MAX_RXD; -	pp->tx_ring_size = ring->tx_pending < MVNETA_MAX_TXD ? -		ring->tx_pending : MVNETA_MAX_TXD; + +	pp->tx_ring_size = clamp_t(u16, ring->tx_pending, +				   MVNETA_MAX_SKB_DESCS * 2, MVNETA_MAX_TXD); +	if (pp->tx_ring_size != ring->tx_pending) +		netdev_warn(dev, "TX queue size set to %u (requested %u)\n", +			    pp->tx_ring_size, ring->tx_pending);  	if (netif_running(dev)) {  		mvneta_stop(dev); @@ -2615,7 +2788,6 @@ static const struct net_device_ops mvneta_netdev_ops = {  	.ndo_set_rx_mode     = mvneta_set_rx_mode,  	.ndo_set_mac_address = mvneta_set_mac_addr,  	.ndo_change_mtu      = mvneta_change_mtu, -	.ndo_tx_timeout      = mvneta_tx_timeout,  	.ndo_get_stats64     = mvneta_get_stats64,  	.ndo_do_ioctl        = mvneta_ioctl,  }; @@ -2632,7 +2804,7 @@ const struct ethtool_ops mvneta_eth_tool_ops = {  };  /* Initialize hw */ -static int mvneta_init(struct mvneta_port *pp, int phy_addr) +static int mvneta_init(struct device *dev, struct mvneta_port *pp)  {  	int queue; @@ -2642,8 +2814,8 @@ static int mvneta_init(struct mvneta_port *pp, int phy_addr)  	/* Set port default values */  	mvneta_defaults_set(pp); -	pp->txqs = kzalloc(txq_number * sizeof(struct mvneta_tx_queue), -			   GFP_KERNEL); +	pp->txqs = devm_kcalloc(dev, txq_number, sizeof(struct mvneta_tx_queue), +				GFP_KERNEL);  	if (!pp->txqs)  		return -ENOMEM; @@ -2655,12 +2827,10 @@ static int mvneta_init(struct mvneta_port *pp, int phy_addr)  		txq->done_pkts_coal = MVNETA_TXDONE_COAL_PKTS;  	} -	pp->rxqs = kzalloc(rxq_number * sizeof(struct mvneta_rx_queue), -			   GFP_KERNEL); -	if (!pp->rxqs) { -		kfree(pp->txqs); +	pp->rxqs = devm_kcalloc(dev, rxq_number, sizeof(struct mvneta_rx_queue), +				GFP_KERNEL); +	if (!pp->rxqs)  		return -ENOMEM; -	}  	/* Create Rx descriptor rings */  	for (queue = 0; queue < rxq_number; queue++) { @@ -2674,12 +2844,6 @@ static int mvneta_init(struct mvneta_port *pp, int phy_addr)  	return 0;  } -static void mvneta_deinit(struct mvneta_port *pp) -{ -	kfree(pp->txqs); -	kfree(pp->rxqs); -} -  /* platform glue : initialize decoding windows */  static void mvneta_conf_mbus_windows(struct mvneta_port *pp,  				     const struct mbus_dram_target_info *dram) @@ -2715,35 +2879,53 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,  }  /* Power up the port */ -static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) +static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)  { -	u32 val; +	u32 ctrl;  	/* MAC Cause register should be cleared */  	mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); -	if (phy_mode == PHY_INTERFACE_MODE_SGMII) -		mvneta_port_sgmii_config(pp); +	ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2); -	mvneta_gmac_rgmii_set(pp, 1); +	/* Even though it might look weird, when we're configured in +	 * SGMII or QSGMII mode, the RGMII bit needs to be set. +	 */ +	switch(phy_mode) { +	case PHY_INTERFACE_MODE_QSGMII: +		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO); +		ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; +		break; +	case PHY_INTERFACE_MODE_SGMII: +		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); +		ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; +		break; +	case PHY_INTERFACE_MODE_RGMII: +	case PHY_INTERFACE_MODE_RGMII_ID: +		ctrl |= MVNETA_GMAC2_PORT_RGMII; +		break; +	default: +		return -EINVAL; +	}  	/* Cancel Port Reset */ -	val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); -	val &= ~MVNETA_GMAC2_PORT_RESET; -	mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); +	ctrl &= ~MVNETA_GMAC2_PORT_RESET; +	mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl);  	while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) &  		MVNETA_GMAC2_PORT_RESET) != 0)  		continue; + +	return 0;  }  /* Device initialization routine */  static int mvneta_probe(struct platform_device *pdev)  {  	const struct mbus_dram_target_info *dram_target_info; +	struct resource *res;  	struct device_node *dn = pdev->dev.of_node;  	struct device_node *phy_node; -	u32 phy_addr;  	struct mvneta_port *pp;  	struct net_device *dev;  	const char *dt_mac_addr; @@ -2772,9 +2954,22 @@ static int mvneta_probe(struct platform_device *pdev)  	phy_node = of_parse_phandle(dn, "phy", 0);  	if (!phy_node) { -		dev_err(&pdev->dev, "no associated PHY\n"); -		err = -ENODEV; -		goto err_free_irq; +		if (!of_phy_is_fixed_link(dn)) { +			dev_err(&pdev->dev, "no PHY specified\n"); +			err = -ENODEV; +			goto err_free_irq; +		} + +		err = of_phy_register_fixed_link(dn); +		if (err < 0) { +			dev_err(&pdev->dev, "cannot register fixed PHY\n"); +			goto err_free_irq; +		} + +		/* In the case of a fixed PHY, the DT node associated +		 * to the PHY is the Ethernet MAC DT node. +		 */ +		phy_node = dn;  	}  	phy_mode = of_get_phy_mode(dn); @@ -2788,11 +2983,9 @@ static int mvneta_probe(struct platform_device *pdev)  	dev->watchdog_timeo = 5 * HZ;  	dev->netdev_ops = &mvneta_netdev_ops; -	SET_ETHTOOL_OPS(dev, &mvneta_eth_tool_ops); +	dev->ethtool_ops = &mvneta_eth_tool_ops;  	pp = netdev_priv(dev); - -	pp->weight = MVNETA_RX_POLL_WEIGHT;  	pp->phy_node = phy_node;  	pp->phy_interface = phy_mode; @@ -2804,14 +2997,22 @@ static int mvneta_probe(struct platform_device *pdev)  	clk_prepare_enable(pp->clk); -	pp->base = of_iomap(dn, 0); -	if (pp->base == NULL) { +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	pp->base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(pp->base)) { +		err = PTR_ERR(pp->base); +		goto err_clk; +	} + +	/* Alloc per-cpu stats */ +	pp->stats = netdev_alloc_pcpu_stats(struct mvneta_pcpu_stats); +	if (!pp->stats) {  		err = -ENOMEM;  		goto err_clk;  	}  	dt_mac_addr = of_get_mac_address(dn); -	if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) { +	if (dt_mac_addr) {  		mac_from = "device tree";  		memcpy(dev->dev_addr, dt_mac_addr, ETH_ALEN);  	} else { @@ -2825,39 +3026,38 @@ static int mvneta_probe(struct platform_device *pdev)  		}  	} -	pp->tx_done_timer.data = (unsigned long)dev; -	pp->tx_done_timer.function = mvneta_tx_done_timer_callback; -	init_timer(&pp->tx_done_timer); -	clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); -  	pp->tx_ring_size = MVNETA_MAX_TXD;  	pp->rx_ring_size = MVNETA_MAX_RXD;  	pp->dev = dev;  	SET_NETDEV_DEV(dev, &pdev->dev); -	err = mvneta_init(pp, phy_addr); +	err = mvneta_init(&pdev->dev, pp); +	if (err < 0) +		goto err_free_stats; + +	err = mvneta_port_power_up(pp, phy_mode);  	if (err < 0) { -		dev_err(&pdev->dev, "can't init eth hal\n"); -		goto err_unmap; +		dev_err(&pdev->dev, "can't power up port\n"); +		goto err_free_stats;  	} -	mvneta_port_power_up(pp, phy_mode);  	dram_target_info = mv_mbus_dram_info();  	if (dram_target_info)  		mvneta_conf_mbus_windows(pp, dram_target_info); -	netif_napi_add(dev, &pp->napi, mvneta_poll, pp->weight); +	netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT); -	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; -	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM; -	dev->vlan_features |= NETIF_F_SG | NETIF_F_IP_CSUM; +	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; +	dev->hw_features |= dev->features; +	dev->vlan_features |= dev->features;  	dev->priv_flags |= IFF_UNICAST_FLT; +	dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;  	err = register_netdev(dev);  	if (err < 0) {  		dev_err(&pdev->dev, "failed to register\n"); -		goto err_deinit; +		goto err_free_stats;  	}  	netdev_info(dev, "Using %s mac address %pM\n", mac_from, @@ -2867,10 +3067,8 @@ static int mvneta_probe(struct platform_device *pdev)  	return 0; -err_deinit: -	mvneta_deinit(pp); -err_unmap: -	iounmap(pp->base); +err_free_stats: +	free_percpu(pp->stats);  err_clk:  	clk_disable_unprepare(pp->clk);  err_free_irq: @@ -2887,9 +3085,8 @@ static int mvneta_remove(struct platform_device *pdev)  	struct mvneta_port *pp = netdev_priv(dev);  	unregister_netdev(dev); -	mvneta_deinit(pp);  	clk_disable_unprepare(pp->clk); -	iounmap(pp->base); +	free_percpu(pp->stats);  	irq_dispose_mapping(dev->irq);  	free_netdev(dev); @@ -2921,3 +3118,4 @@ module_param(rxq_number, int, S_IRUGO);  module_param(txq_number, int, S_IRUGO);  module_param(rxq_def, int, S_IRUGO); +module_param(rx_copybreak, int, S_IRUGO | S_IWUSR); diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 4ae0c742601..8f5aa7c62b1 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -19,11 +19,9 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */ -#include <linux/init.h>  #include <linux/dma-mapping.h>  #include <linux/in.h>  #include <linux/ip.h> @@ -321,23 +319,6 @@ static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr)  	wrl(pep, PHY_ADDRESS, reg_data);  } -static void ethernet_phy_reset(struct pxa168_eth_private *pep) -{ -	int data; - -	data = phy_read(pep->phy, MII_BMCR); -	if (data < 0) -		return; - -	data |= BMCR_RESET; -	if (phy_write(pep->phy, MII_BMCR, data) < 0) -		return; - -	do { -		data = phy_read(pep->phy, MII_BMCR); -	} while (data >= 0 && data & BMCR_RESET); -} -  static void rxq_refill(struct net_device *dev)  {  	struct pxa168_eth_private *pep = netdev_priv(dev); @@ -646,7 +627,7 @@ static void eth_port_start(struct net_device *dev)  		struct ethtool_cmd cmd;  		pxa168_get_settings(pep->dev, &cmd); -		ethernet_phy_reset(pep); +		phy_init_hw(pep->phy);  		pxa168_set_settings(pep->dev, &cmd);  	} @@ -1123,8 +1104,7 @@ static int pxa168_eth_open(struct net_device *dev)  	struct pxa168_eth_private *pep = netdev_priv(dev);  	int err; -	err = request_irq(dev->irq, pxa168_eth_int_handler, -			  IRQF_DISABLED, dev->name, dev); +	err = request_irq(dev->irq, pxa168_eth_int_handler, 0, dev->name, dev);  	if (err) {  		dev_err(&dev->dev, "can't assign irq\n");  		return -EAGAIN; @@ -1384,7 +1364,6 @@ static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr)  static void phy_init(struct pxa168_eth_private *pep, int speed, int duplex)  {  	struct phy_device *phy = pep->phy; -	ethernet_phy_reset(pep);  	phy_attach(pep->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_MII); @@ -1509,7 +1488,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)  	dev->netdev_ops = &pxa168_eth_netdev_ops;  	dev->watchdog_timeo = 2 * HZ;  	dev->base_addr = 0; -	SET_ETHTOOL_OPS(dev, &pxa168_ethtool_ops); +	dev->ethtool_ops = &pxa168_ethtool_ops;  	INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index ef94a591f9e..e912b6887d4 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -2845,7 +2845,7 @@ mapping_unwind:  mapping_error:  	if (net_ratelimit())  		dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); -	dev_kfree_skb(skb); +	dev_kfree_skb_any(skb);  	return NETDEV_TX_OK;  } @@ -3086,23 +3086,27 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,  					       PCI_DMA_FROMDEVICE);  		skge_rx_reuse(e, skge->rx_buf_size);  	} else { +		struct skge_element ee;  		struct sk_buff *nskb;  		nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size);  		if (!nskb)  			goto resubmit; +		ee = *e; + +		skb = ee.skb; +		prefetch(skb->data); +  		if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) {  			dev_kfree_skb(nskb);  			goto resubmit;  		}  		pci_unmap_single(skge->hw->pdev, -				 dma_unmap_addr(e, mapaddr), -				 dma_unmap_len(e, maplen), +				 dma_unmap_addr(&ee, mapaddr), +				 dma_unmap_len(&ee, maplen),  				 PCI_DMA_FROMDEVICE); -		skb = e->skb; -		prefetch(skb->data);  	}  	skb_put(skb, len); @@ -3168,7 +3172,7 @@ static void skge_tx_done(struct net_device *dev)  			pkts_compl++;  			bytes_compl += e->skb->len; -			dev_kfree_skb(e->skb); +			dev_consume_skb_any(e->skb);  		}  	}  	netdev_completed_queue(dev, pkts_compl, bytes_compl); @@ -4042,7 +4046,6 @@ err_out_free_regions:  	pci_release_regions(pdev);  err_out_disable_pdev:  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  err_out:  	return err;  } @@ -4086,7 +4089,6 @@ static void skge_remove(struct pci_dev *pdev)  	iounmap(hw->regs);  	kfree(hw); -	pci_set_drvdata(pdev, NULL);  }  #ifdef CONFIG_PM_SLEEP @@ -4197,6 +4199,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = {  			DMI_MATCH(DMI_BOARD_NAME, "P5NSLI")  		},  	}, +	{ +		.ident = "FUJITSU SIEMENS A8NE-FM", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), +			DMI_MATCH(DMI_BOARD_NAME, "A8NE-FM") +		}, +	},  	{}  }; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index e09a8c6f853..69693384b58 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -44,6 +44,8 @@  #include <linux/prefetch.h>  #include <linux/debugfs.h>  #include <linux/mii.h> +#include <linux/of_device.h> +#include <linux/of_net.h>  #include <asm/irq.h> @@ -2000,7 +2002,7 @@ mapping_unwind:  mapping_error:  	if (net_ratelimit())  		dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); -	dev_kfree_skb(skb); +	dev_kfree_skb_any(skb);  	return NETDEV_TX_OK;  } @@ -2495,7 +2497,7 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,  		skb_copy_from_linear_data(re->skb, skb->data, length);  		skb->ip_summed = re->skb->ip_summed;  		skb->csum = re->skb->csum; -		skb->rxhash = re->skb->rxhash; +		skb_copy_hash(skb, re->skb);  		skb->vlan_proto = re->skb->vlan_proto;  		skb->vlan_tci = re->skb->vlan_tci; @@ -2503,7 +2505,7 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,  					       length, PCI_DMA_FROMDEVICE);  		re->skb->vlan_proto = 0;  		re->skb->vlan_tci = 0; -		re->skb->rxhash = 0; +		skb_clear_hash(re->skb);  		re->skb->ip_summed = CHECKSUM_NONE;  		skb_put(skb, length);  	} @@ -2723,7 +2725,7 @@ static void sky2_rx_hash(struct sky2_port *sky2, u32 status)  	struct sk_buff *skb;  	skb = sky2->rx_ring[sky2->rx_next].skb; -	skb->rxhash = le32_to_cpu(status); +	skb_set_hash(skb, le32_to_cpu(status), PKT_HASH_TYPE_L3);  }  /* Process status response ring */ @@ -2733,6 +2735,9 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)  	unsigned int total_bytes[2] = { 0 };  	unsigned int total_packets[2] = { 0 }; +	if (to_do <= 0) +		return work_done; +  	rmb();  	do {  		struct sky2_port *sky2; @@ -3906,19 +3911,19 @@ static struct rtnl_link_stats64 *sky2_get_stats(struct net_device *dev,  	u64 _bytes, _packets;  	do { -		start = u64_stats_fetch_begin_bh(&sky2->rx_stats.syncp); +		start = u64_stats_fetch_begin_irq(&sky2->rx_stats.syncp);  		_bytes = sky2->rx_stats.bytes;  		_packets = sky2->rx_stats.packets; -	} while (u64_stats_fetch_retry_bh(&sky2->rx_stats.syncp, start)); +	} while (u64_stats_fetch_retry_irq(&sky2->rx_stats.syncp, start));  	stats->rx_packets = _packets;  	stats->rx_bytes = _bytes;  	do { -		start = u64_stats_fetch_begin_bh(&sky2->tx_stats.syncp); +		start = u64_stats_fetch_begin_irq(&sky2->tx_stats.syncp);  		_bytes = sky2->tx_stats.bytes;  		_packets = sky2->tx_stats.packets; -	} while (u64_stats_fetch_retry_bh(&sky2->tx_stats.syncp, start)); +	} while (u64_stats_fetch_retry_irq(&sky2->tx_stats.syncp, start));  	stats->tx_packets = _packets;  	stats->tx_bytes = _bytes; @@ -4748,13 +4753,14 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,  {  	struct sky2_port *sky2;  	struct net_device *dev = alloc_etherdev(sizeof(*sky2)); +	const void *iap;  	if (!dev)  		return NULL;  	SET_NETDEV_DEV(dev, &hw->pdev->dev);  	dev->irq = hw->pdev->irq; -	SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops); +	dev->ethtool_ops = &sky2_ethtool_ops;  	dev->watchdog_timeo = TX_WATCHDOG;  	dev->netdev_ops = &sky2_netdev_ops[port]; @@ -4763,6 +4769,9 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,  	sky2->hw = hw;  	sky2->msg_enable = netif_msg_init(debug, default_msg); +	u64_stats_init(&sky2->tx_stats.syncp); +	u64_stats_init(&sky2->rx_stats.syncp); +  	/* Auto speed and flow control */  	sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE;  	if (hw->chip_id != CHIP_ID_YUKON_XL) @@ -4802,8 +4811,16 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,  	dev->features |= dev->hw_features; -	/* read the mac address */ -	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); +	/* try to get mac address in the following order: +	 * 1) from device tree data +	 * 2) from internal registers set by bootloader +	 */ +	iap = of_get_mac_address(hw->pdev->dev.of_node); +	if (iap) +		memcpy(dev->dev_addr, iap, ETH_ALEN); +	else +		memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, +			      ETH_ALEN);  	return dev;  } @@ -5017,6 +5034,8 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		}   	} +	netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT); +  	err = register_netdev(dev);  	if (err) {  		dev_err(&pdev->dev, "cannot register net device\n"); @@ -5025,8 +5044,6 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	netif_carrier_off(dev); -	netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT); -  	sky2_show_addr(dev);  	if (hw->ports > 1) { @@ -5081,7 +5098,6 @@ err_out_free_regions:  err_out_disable:  	pci_disable_device(pdev);  err_out: -	pci_set_drvdata(pdev, NULL);  	return err;  } @@ -5124,8 +5140,6 @@ static void sky2_remove(struct pci_dev *pdev)  	iounmap(hw->regs);  	kfree(hw); - -	pci_set_drvdata(pdev, NULL);  }  static int sky2_suspend(struct device *dev)  | 
