Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next 3/3] sunvnet: generate ICMP PTMUD messages for smaller port MTUs
From: David Miller @ 2014-09-12 22:26 UTC (permalink / raw)
  To: david.stevens; +Cc: netdev
In-Reply-To: <5413723C.7040607@oracle.com>

From: David L Stevens <david.stevens@oracle.com>
Date: Fri, 12 Sep 2014 18:22:52 -0400

> +		if (skb->protocol == htons(ETH_P_IP))
> +		{

Openning braces should be on the same line as the if() statement.

^ permalink raw reply

* Re: [PATCH Resend] drivers: net: b44: Fix typo in returning multicast stats
From: David Miller @ 2014-09-12 22:24 UTC (permalink / raw)
  To: mark.einon; +Cc: gary.zambrano, netdev, linux-kernel
In-Reply-To: <1410473989-2049-1-git-send-email-mark.einon@gmail.com>

From: Mark Einon <mark.einon@gmail.com>
Date: Thu, 11 Sep 2014 23:19:49 +0100

> nstat->multicast refers to received packets, not transmitted as
> is returned here. Change it so that received packet stats are
> given.
> 
> Signed-off-by: Mark Einon <mark.einon@gmail.com>

Applied, thank you.

^ permalink raw reply

* [PATCH net-next 3/3] sunvnet: generate ICMP PTMUD messages for smaller port MTUs
From: David L Stevens @ 2014-09-12 22:22 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

This patch sends ICMP and ICMPv6 messages for Path MTU Discovery when a remote
port MTU is smaller than the device MTU. This allows mixing newer VIO protocol
devices that support MTU negotiation with older devices that do not on the
same vswitch. It also allows Linux-Linux LDOMs to use 64K-1 data packets even
though Solaris vswitch is limited to <16K MTU.

Signed-off-by: David L Stevens <david.stevens@oracle.com>
---
 drivers/net/ethernet/sun/sunvnet.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index b557ec4..1251603 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -17,6 +17,13 @@
 #include <linux/mutex.h>
 #include <linux/if_vlan.h>
 +#if IS_ENABLED(CONFIG_IPV6)
+#include <linux/icmpv6.h>
+#endif
+
+#include <net/icmp.h>
+#include <net/route.h>
+
 #include <asm/vio.h>
 #include <asm/ldc.h>
 @@ -752,6 +759,34 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto out_dropped;
  	if (skb->len > port->vio.rmtu) {
+		unsigned long localmtu = port->vio.rmtu - ETH_HLEN;
+
+		if (port->vio.ver.major == 1 && port->vio.ver.minor >= 3)
+			localmtu -= VLAN_HLEN;
+
+		if (skb->protocol == htons(ETH_P_IP))
+		{
+			struct flowi4 fl4;
+			struct rtable *rt = NULL;
+
+			memset(&fl4, 0, sizeof(fl4));
+			fl4.flowi4_oif = dev->ifindex;
+			fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
+			fl4.daddr = ip_hdr(skb)->daddr;
+			fl4.saddr = ip_hdr(skb)->saddr;
+
+			rt = ip_route_output_key(dev_net(dev), &fl4);
+			if (!IS_ERR(rt)) {
+				skb_dst_set(skb, &rt->dst);
+				icmp_send(skb, ICMP_DEST_UNREACH,
+					  ICMP_FRAG_NEEDED,
+					  htonl(localmtu));
+			}
+		}
+#if IS_ENABLED(CONFIG_IPV6)
+		else if (skb->protocol == htons(ETH_P_IPV6))
+			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu);
+#endif
 		goto out_dropped;
 	}
 -- 1.7.1

^ permalink raw reply related

* [PATCH net-next 2/3] sunvnet: allow admin to set sunvnet MTU
From: David L Stevens @ 2014-09-12 22:22 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

This patch allows an admin to set the MTU on a sunvnet device to arbitrary
values between the minimum (68) and maximum (65535) IPv4 packet sizes.

Signed-off-by: David L Stevens <david.stevens@oracle.com>
---
 drivers/net/ethernet/sun/sunvnet.c |    6 +++++-
 drivers/net/ethernet/sun/sunvnet.h |    2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index a6418bb..b557ec4 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -751,6 +751,10 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (unlikely(!port))
 		goto out_dropped;
 +	if (skb->len > port->vio.rmtu) {
+		goto out_dropped;
+	}
+
 	spin_lock_irqsave(&port->vio.lock, flags);
  	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
@@ -972,7 +976,7 @@ static void vnet_set_rx_mode(struct net_device *dev)
  static int vnet_change_mtu(struct net_device *dev, int new_mtu)
 {
-	if (new_mtu != ETH_DATA_LEN)
+	if (new_mtu < 68 || new_mtu > 65535)
 		return -EINVAL;
  	dev->mtu = new_mtu;
diff --git a/drivers/net/ethernet/sun/sunvnet.h b/drivers/net/ethernet/sun/sunvnet.h
index 243ae69..fcf0129 100644
--- a/drivers/net/ethernet/sun/sunvnet.h
+++ b/drivers/net/ethernet/sun/sunvnet.h
@@ -11,7 +11,7 @@
  */
 #define VNET_TX_TIMEOUT			(5 * HZ)
 -#define VNET_MAXPACKET			1518ULL /* ETH_FRAMELEN + VLAN_HDR */
+#define VNET_MAXPACKET			65553ULL /* 64K-1  +ETH HDR +VLAN HDR*/
 #define VNET_TX_RING_SIZE		512
 #define VNET_TX_WAKEUP_THRESH(dr)	((dr)->pending / 4)
 -- 1.7.1

^ permalink raw reply related

* [PATCH net-next 1/3] sunvnet: upgrade to VIO protocol version 1.6
From: David L Stevens @ 2014-09-12 22:22 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

This patch upgrades the sunvnet driver to support VIO protocol version 1.6.
In particular, it adds per-port MTU negotiation, allowing MTUs other than
ETH_FRAMELEN with ports using newer VIO protocol versions.

Signed-off-by: David L Stevens <david.stevens@oracle.com>
---
 arch/sparc/include/asm/vio.h       |   19 ++++++-
 arch/sparc/kernel/viohs.c          |   14 +++++-
 drivers/net/ethernet/sun/sunvnet.c |   96 ++++++++++++++++++++++++++++++------
 drivers/net/ethernet/sun/sunvnet.h |    1 +
 4 files changed, 110 insertions(+), 20 deletions(-)

diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h
index 5c0ebe7..da13e3b 100644
--- a/arch/sparc/include/asm/vio.h
+++ b/arch/sparc/include/asm/vio.h
@@ -65,6 +65,7 @@ struct vio_dring_register {
 	u16			options;
 #define VIO_TX_DRING		0x0001
 #define VIO_RX_DRING		0x0002
+#define VIO_RX_DRING_DATA	0x0004
 	u16			resv;
 	u32			num_cookies;
 	struct ldc_trans_cookie	cookies[0];
@@ -80,6 +81,8 @@ struct vio_dring_unregister {
 #define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
 #define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
 #define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
+/* in vers >= 1.2, VIO_DRING_MODE is 0x04 and transfer mode is a bitmask */
+#define VIO_NEW_DRING_MODE	0x04
  struct vio_dring_data {
 	struct vio_msg_tag	tag;
@@ -209,10 +212,20 @@ struct vio_net_attr_info {
 	u8			addr_type;
 #define VNET_ADDR_ETHERMAC	0x01
 	u16			ack_freq;
-	u32			resv1;
+	u8			plnk_updt;
+#define PHYSLINK_UPDATE_NONE		0x00
+#define PHYSLINK_UPDATE_STATE		0x01
+#define PHYSLINK_UPDATE_STATE_ACK	0x02
+#define PHYSLINK_UPDATE_STATE_NACK	0x03
+	u8			options;
+	u16			resv1;
 	u64			addr;
 	u64			mtu;
-	u64			resv2[3];
+	u16			cflags;
+#define VNET_LSO_IPV4_CAPAB		0x0001
+	u16			ipv4_lso_maxlen;
+	u32			resv2;
+	u64			resv3[2];
 };
  #define VNET_NUM_MCAST		7
@@ -368,6 +381,8 @@ struct vio_driver_state {
 	char			*name;
  	struct vio_driver_ops	*ops;
+
+	u64			rmtu;	/* remote MTU */
 };
  #define viodbg(TYPE, f, a...) \
diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c
index f8e7dd5..446438b 100644
--- a/arch/sparc/kernel/viohs.c
+++ b/arch/sparc/kernel/viohs.c
@@ -426,6 +426,13 @@ static int process_dreg_info(struct vio_driver_state *vio,
 	if (vio->dr_state & VIO_DR_STATE_RXREG)
 		goto send_nack;
 +	/* v1.6 and higher, ACK with desired, supported mode, or NACK */
+	if (vio->ver.major <= 1 && vio->ver.minor >= 6) {
+		if (!(pkt->options & VIO_TX_DRING))
+			goto send_nack;
+		pkt->options = VIO_TX_DRING;
+	}
+
 	BUG_ON(vio->desc_buf);
  	vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
@@ -453,8 +460,11 @@ static int process_dreg_info(struct vio_driver_state *vio,
 	pkt->tag.stype = VIO_SUBTYPE_ACK;
 	pkt->dring_ident = ++dr->ident;
 -	viodbg(HS, "SEND DRING_REG ACK ident[%llx]\n",
-	       (unsigned long long) pkt->dring_ident);
+	viodbg(HS, "SEND DRING_REG ACK ident[%llx] "
+	       "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
+	       (unsigned long long) pkt->dring_ident,
+	       pkt->num_descr, pkt->descr_size, pkt->options,
+	       pkt->num_cookies);
  	len = (sizeof(*pkt) +
 	       (dr->ncookies * sizeof(struct ldc_trans_cookie)));
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index a4657a4..a6418bb 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -15,6 +15,7 @@
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/mutex.h>
+#include <linux/if_vlan.h>
  #include <asm/vio.h>
 #include <asm/ldc.h>
@@ -39,6 +40,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
  /* Ordered from largest major to lowest */
 static struct vio_version vnet_versions[] = {
+	{ .major = 1, .minor = 6 },
 	{ .major = 1, .minor = 0 },
 };
 @@ -65,6 +67,7 @@ static int vnet_send_attr(struct vio_driver_state *vio)
 	struct vnet_port *port = to_vnet_port(vio);
 	struct net_device *dev = port->vp->dev;
 	struct vio_net_attr_info pkt;
+	int framelen = ETH_FRAME_LEN;
 	int i;
  	memset(&pkt, 0, sizeof(pkt));
@@ -72,19 +75,37 @@ static int vnet_send_attr(struct vio_driver_state *vio)
 	pkt.tag.stype = VIO_SUBTYPE_INFO;
 	pkt.tag.stype_env = VIO_ATTR_INFO;
 	pkt.tag.sid = vio_send_sid(vio);
-	pkt.xfer_mode = VIO_DRING_MODE;
+	if (vio->ver.major <= 1 && vio->ver.minor < 2)
+		pkt.xfer_mode = VIO_DRING_MODE;
+	else
+		pkt.xfer_mode = VIO_NEW_DRING_MODE;
 	pkt.addr_type = VNET_ADDR_ETHERMAC;
 	pkt.ack_freq = 0;
 	for (i = 0; i < 6; i++)
 		pkt.addr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
-	pkt.mtu = ETH_FRAME_LEN;
+	if (vio->ver.major == 1) {
+		if (vio->ver.minor > 3) {
+			if (vio->rmtu)
+				vio->rmtu = pkt.mtu = min(VNET_MAXPACKET,
+							  vio->rmtu);
+			else
+				vio->rmtu = pkt.mtu = VNET_MAXPACKET;
+		} else if (vio->ver.minor == 3)
+			pkt.mtu = framelen + VLAN_HLEN;
+		else
+			pkt.mtu = framelen;
+		if (vio->ver.minor >= 6)
+			pkt.options = VIO_TX_DRING;
+	}
  	viodbg(HS, "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
-	       "ackfreq[%u] mtu[%llu]\n",
+	       "ackfreq[%u] plnk_updt[0x%02x] opts[0x%02x] mtu[%llu] "
+	       "cflags[0x%04x] lso_max[%u]\n",
 	       pkt.xfer_mode, pkt.addr_type,
 	       (unsigned long long) pkt.addr,
-	       pkt.ack_freq,
-	       (unsigned long long) pkt.mtu);
+	       pkt.ack_freq, pkt.plnk_updt, pkt.options,
+	       (unsigned long long) pkt.mtu, pkt.cflags, pkt.ipv4_lso_maxlen);
+
  	return vio_ldc_send(vio, &pkt, sizeof(pkt));
 }
@@ -92,18 +113,52 @@ static int vnet_send_attr(struct vio_driver_state *vio)
 static int handle_attr_info(struct vio_driver_state *vio,
 			    struct vio_net_attr_info *pkt)
 {
-	viodbg(HS, "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] "
-	       "ackfreq[%u] mtu[%llu]\n",
+	u64	localmtu;
+	u8	xfer_mode;
+
+	viodbg(HS, "GOT NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
+	       "ackfreq[%u] plnk_updt[0x%02x] opts[0x%02x] mtu[%llu] "
+	       " (rmtu[%llu]) cflags[0x%04x] lso_max[%u]\n",
 	       pkt->xfer_mode, pkt->addr_type,
 	       (unsigned long long) pkt->addr,
-	       pkt->ack_freq,
-	       (unsigned long long) pkt->mtu);
+	       pkt->ack_freq, pkt->plnk_updt, pkt->options,
+	       (unsigned long long) pkt->mtu, vio->rmtu, pkt->cflags,
+	       pkt->ipv4_lso_maxlen);
  	pkt->tag.sid = vio_send_sid(vio);
 -	if (pkt->xfer_mode != VIO_DRING_MODE ||
+	xfer_mode = pkt->xfer_mode;
+	/* for version < 1.2, VIO_DRING_MODE = 0x3 and no bitmask */
+	if ((vio->ver.major <= 1 &&  vio->ver.minor < 2) &&
+	    xfer_mode == VIO_DRING_MODE)
+		xfer_mode = VIO_NEW_DRING_MODE;
+
+	/* MTU negotiation:
+	 *	< v1.3 - ETH_FRAME_LEN exactly
+	 *	= v1.3 - ETH_FRAME_LEN + VLAN_HLEN exactly
+	 *	> v1.4 - MIN(pkt.mtu, VNET_MAX_PACKET, vio->rmtu) and change
+	 *			pkt->mtu for ACK
+	 */
+	if (vio->ver.major == 1 && vio->ver.minor < 3) {
+		localmtu = ETH_FRAME_LEN;
+	} else if (vio->ver.major == 1 && vio->ver.minor == 3) {
+		localmtu = ETH_FRAME_LEN + VLAN_HLEN;
+	} else {
+		localmtu = vio->rmtu ? vio->rmtu : VNET_MAXPACKET;
+		localmtu = pkt->mtu = min(pkt->mtu, localmtu);
+	}
+	vio->rmtu = localmtu;
+
+
+	/* for version >= 1.6, ACK packet mode we support */
+	if (vio->ver.major <= 1 && vio->ver.minor >= 6) {
+		pkt->xfer_mode = VIO_NEW_DRING_MODE;
+		pkt->options = VIO_TX_DRING;
+	}
+
+	if (!(xfer_mode | VIO_NEW_DRING_MODE) ||
 	    pkt->addr_type != VNET_ADDR_ETHERMAC ||
-	    pkt->mtu != ETH_FRAME_LEN) {
+	    pkt->mtu != localmtu) {
 		viodbg(HS, "SEND NET ATTR NACK\n");
  		pkt->tag.stype = VIO_SUBTYPE_NACK;
@@ -112,7 +167,14 @@ static int handle_attr_info(struct vio_driver_state *vio,
  		return -ECONNRESET;
 	} else {
-		viodbg(HS, "SEND NET ATTR ACK\n");
+		viodbg(HS, "SEND NET ATTR ACK xmode[0x%x] atype[0x%x] "
+		       "addr[%llx] ackfreq[%u] plnk_updt[0x%02x] opts[0x%02x] "
+		       "mtu[%llu] (rmtu[%llu]) cflags[0x%04x] lso_max[%u]\n",
+		       pkt->xfer_mode, pkt->addr_type,
+		       (unsigned long long) pkt->addr,
+		       pkt->ack_freq, pkt->plnk_updt, pkt->options,
+		       (unsigned long long) pkt->mtu, vio->rmtu, pkt->cflags,
+		       pkt->ipv4_lso_maxlen);
  		pkt->tag.stype = VIO_SUBTYPE_ACK;
 @@ -208,7 +270,7 @@ static int vnet_rx_one(struct vnet_port *port, unsigned int len,
 	int err;
  	err = -EMSGSIZE;
-	if (unlikely(len < ETH_ZLEN || len > ETH_FRAME_LEN)) {
+	if (unlikely(len < ETH_ZLEN || len > port->vio.rmtu)) {
 		dev->stats.rx_length_errors++;
 		goto out_dropped;
 	}
@@ -528,8 +590,10 @@ static void vnet_event(void *arg, int event)
 		vio_link_state_change(vio, event);
 		spin_unlock_irqrestore(&vio->lock, flags);
 -		if (event == LDC_EVENT_RESET)
+		if (event == LDC_EVENT_RESET) {
+			vio->rmtu = 0;
 			vio_port_up(vio);
+		}
 		return;
 	}
 @@ -986,8 +1050,8 @@ static int vnet_port_alloc_tx_bufs(struct vnet_port *port)
 	void *dring;
  	for (i = 0; i < VNET_TX_RING_SIZE; i++) {
-		void *buf = kzalloc(ETH_FRAME_LEN + 8, GFP_KERNEL);
-		int map_len = (ETH_FRAME_LEN + 7) & ~7;
+		void *buf = kzalloc(VNET_MAXPACKET + 8, GFP_KERNEL);
+		int map_len = (VNET_MAXPACKET + 7) & ~7;
  		err = -ENOMEM;
 		if (!buf)
diff --git a/drivers/net/ethernet/sun/sunvnet.h b/drivers/net/ethernet/sun/sunvnet.h
index de5c2c6..243ae69 100644
--- a/drivers/net/ethernet/sun/sunvnet.h
+++ b/drivers/net/ethernet/sun/sunvnet.h
@@ -11,6 +11,7 @@
  */
 #define VNET_TX_TIMEOUT			(5 * HZ)
 +#define VNET_MAXPACKET			1518ULL /* ETH_FRAMELEN + VLAN_HDR */
 #define VNET_TX_RING_SIZE		512
 #define VNET_TX_WAKEUP_THRESH(dr)	((dr)->pending / 4)
 -- 1.7.1

^ permalink raw reply related

* [PATCH net-next 0/3] sunvnet: add jumbo frames support
From: David L Stevens @ 2014-09-12 22:22 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

This patch set updates the sunvnet driver to version 1.6 of the VIO protocol
to support per-port exchange of MTU information and allow non-standard MTU
sizes, including jumbo frames.

Using large MTUs shows a > 4X throughput improvement Linux-Solaris
and > 8X throughput improvement Linux-Linux.

David L Stevens (3):
  sunvnet: upgrade to VIO protocol version 1.6
  sunvnet: allow admin to set sunvnet MTU
  sunvnet: generate ICMP PTMUD messages for smaller port MTUs

 arch/sparc/include/asm/vio.h       |   19 +++++-
 arch/sparc/kernel/viohs.c          |   14 +++-
 drivers/net/ethernet/sun/sunvnet.c |  137 +++++++++++++++++++++++++++++++-----
 drivers/net/ethernet/sun/sunvnet.h |    1 +
 4 files changed, 150 insertions(+), 21 deletions(-)

^ permalink raw reply

* Re: pull request: wireless 2014-09-11
From: David Miller @ 2014-09-12 22:22 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20140911184322.GB22872@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Thu, 11 Sep 2014 14:43:22 -0400

> Please pull this batch of fixes intended for the 3.17 stream:

Pulled, thanks John.

^ permalink raw reply

* Re: [PATCH] net/macb: Add hardware revision information during probe
From: David Miller @ 2014-09-12 22:20 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: nicolas.ferre, linux-arm-kernel, linux-kernel, netdev, voice.shen
In-Reply-To: <1410447096-29980-1-git-send-email-alexandre.belloni@free-electrons.com>

From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Date: Thu, 11 Sep 2014 16:51:36 +0200

> From: Bo Shen <voice.shen@atmel.com>
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>
> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> ---
>  drivers/net/ethernet/cadence/macb.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
> index ca5d7798b265..a3b35c146d9c 100644
> --- a/drivers/net/ethernet/cadence/macb.c
> +++ b/drivers/net/ethernet/cadence/macb.c
> @@ -2241,6 +2241,7 @@ static int __init macb_probe(struct platform_device *pdev)
>  
>  	netif_carrier_off(dev);
>  
> +	netdev_info(dev, "Cadence rev 0x%08x\n", macb_readl(bp, MID));
>  	netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n",
>  		    macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr,
>  		    dev->irq, dev->dev_addr);

This is really sloppy.  The "Cadence %s at ..." is what announces the device,
therefore it's out of context to print out the device revision beforehand.

Why don't you just add it to the existing printout instead?

^ permalink raw reply

* Re: [PATCHv3 net-next] sunvnet: Avoid sending superfluous LDC messages.
From: David Miller @ 2014-09-12 22:19 UTC (permalink / raw)
  To: sowmini.varadhan; +Cc: raghuram.kothakota, netdev, bob.picco
In-Reply-To: <20140911135722.GA22398@oracle.com>

From: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Date: Thu, 11 Sep 2014 09:57:22 -0400

> When sending out a burst of packets across multiple descriptors,
> it is sufficient to send one LDC "start" trigger for
> the first descriptor, so do not send an LDC "start" for every
> pass through vnet_start_xmit. Similarly, it is sufficient to send
> one "DRING_STOPPED" trigger for the last dring (and if that
> fails, hold off and send the trigger later).
> 
> Optimizations to the number of LDC messages helps avoid
> filling up the LDC channel with superfluous LDC messages
> that risk triggering flow-control on the channel,
> and also boosts performance.
> 
> Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
> Acked-by: Raghuram Kothakota <raghuram.kothakota@oracle.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH v2] net/phy: micrel: Disable asymmetric pause for KSZ9031
From: David Miller @ 2014-09-12 22:18 UTC (permalink / raw)
  To: mike.looijmans; +Cc: f.fainelli, netdev, linux-kernel
In-Reply-To: <1410525637-849-1-git-send-email-mike.looijmans@topic.nl>

From: Mike Looijmans <mike.looijmans@topic.nl>
Date: Fri, 12 Sep 2014 14:40:37 +0200

> The KSZ9031 appears to suffer from the same hardware bug as described
> for the KSZ9021 in commit 32fcafbcd1c9f6c7013016a22a5369b4acb93577
> ("net/phy: micrel: Disable asymmetric pause for KSZ9021")
> you have to unplug the cable and plug it back to get it to work.
> 
> Remove the SUPPORTED_Asym_Pause flag for the KSZ9031 to fix this.
> 
> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>

This patch does not apply cleanly to the net tree, please respin.

^ permalink raw reply

* Re: [PATCH] net: DSA: Marvell mv88e6171 switch driver
From: Florian Fainelli @ 2014-09-12 22:17 UTC (permalink / raw)
  To: Andrew Lunn, davem; +Cc: netdev, Claudio Leite
In-Reply-To: <1410559124-10495-1-git-send-email-andrew@lunn.ch>

Hi Andrew,

On 09/12/2014 02:58 PM, Andrew Lunn wrote:
> This is the Marvell driver with some cleanups by Claudio Leite
> and myself.

Looks good to me, this will slightly conflict with the patch for the
tag_protocol field [1], other than that, good to see this driver
submitted! Thanks!

[1]: http://patchwork.ozlabs.org/patch/388484/

> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Cc: Claudio Leite <leitec@staticky.com>
> ---
>  drivers/net/dsa/Kconfig     |   9 +
>  drivers/net/dsa/Makefile    |   3 +
>  drivers/net/dsa/mv88e6171.c | 407 ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/dsa/mv88e6xxx.c |   6 +
>  drivers/net/dsa/mv88e6xxx.h |   1 +
>  5 files changed, 426 insertions(+)
>  create mode 100644 drivers/net/dsa/mv88e6171.c
> 
> diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
> index c6ee07c6a1b5..ea0697eaeff5 100644
> --- a/drivers/net/dsa/Kconfig
> +++ b/drivers/net/dsa/Kconfig
> @@ -36,6 +36,15 @@ config NET_DSA_MV88E6123_61_65
>  	  This enables support for the Marvell 88E6123/6161/6165
>  	  ethernet switch chips.
>  
> +config NET_DSA_MV88E6171
> +	tristate "Marvell 88E6171 ethernet switch chip support"
> +	select NET_DSA
> +	select NET_DSA_MV88E6XXX
> +	select NET_DSA_TAG_EDSA
> +	---help---
> +	  This enables support for the Marvell 88E6171 ethernet switch
> +	  chip.
> +
>  config NET_DSA_BCM_SF2
>  	tristate "Broadcom Starfighter 2 Ethernet switch support"
>  	select NET_DSA
> diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
> index dd3cd3b8157f..23a90de9830e 100644
> --- a/drivers/net/dsa/Makefile
> +++ b/drivers/net/dsa/Makefile
> @@ -7,4 +7,7 @@ endif
>  ifdef CONFIG_NET_DSA_MV88E6131
>  mv88e6xxx_drv-y += mv88e6131.o
>  endif
> +ifdef CONFIG_NET_DSA_MV88E6171
> +mv88e6xxx_drv-y += mv88e6171.o
> +endif
>  obj-$(CONFIG_NET_DSA_BCM_SF2)	+= bcm_sf2.o
> diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
> new file mode 100644
> index 000000000000..8bae73bec1d7
> --- /dev/null
> +++ b/drivers/net/dsa/mv88e6171.c
> @@ -0,0 +1,407 @@
> +/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
> + * Copyright (c) 2008-2009 Marvell Semiconductor
> + * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/jiffies.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/phy.h>
> +#include <net/dsa.h>
> +#include "mv88e6xxx.h"
> +
> +static char *mv88e6171_probe(struct mii_bus *bus, int sw_addr)
> +{
> +	int ret;
> +
> +	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
> +	if (ret >= 0) {
> +		if ((ret & 0xfff0) == 0x1710)
> +			return "Marvell 88E6171";
> +	}
> +
> +	return NULL;
> +}
> +
> +static int mv88e6171_switch_reset(struct dsa_switch *ds)
> +{
> +	int i;
> +	int ret;
> +	unsigned long timeout;
> +
> +	/* Set all ports to the disabled state. */
> +	for (i = 0; i < 8; i++) {
> +		ret = REG_READ(REG_PORT(i), 0x04);
> +		REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
> +	}
> +
> +	/* Wait for transmit queues to drain. */
> +	usleep_range(2000, 4000);
> +
> +	/* Reset the switch. */
> +	REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
> +
> +	/* Wait up to one second for reset to complete. */
> +	timeout = jiffies + 1 * HZ;
> +	while (time_before(jiffies, timeout)) {
> +		ret = REG_READ(REG_GLOBAL, 0x00);
> +		if ((ret & 0xc800) == 0xc800)
> +			break;
> +
> +		usleep_range(1000, 2000);
> +	}
> +	if (time_after(jiffies, timeout))
> +		return -ETIMEDOUT;
> +
> +	/* Enable ports not under DSA, e.g. WAN port */
> +	for (i = 0; i < 8; i++) {
> +		if (dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i))
> +			continue;
> +
> +		ret = REG_READ(REG_PORT(i), 0x04);
> +		REG_WRITE(REG_PORT(i), 0x04, ret | 0x03);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mv88e6171_setup_global(struct dsa_switch *ds)
> +{
> +	int ret;
> +	int i;
> +
> +	/* Disable the PHY polling unit (since there won't be any
> +	 * external PHYs to poll), don't discard packets with
> +	 * excessive collisions, and mask all interrupt sources.
> +	 */
> +	REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
> +
> +	/* Set the default address aging time to 5 minutes, and
> +	 * enable address learn messages to be sent to all message
> +	 * ports.
> +	 */
> +	REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
> +
> +	/* Configure the priority mapping registers. */
> +	ret = mv88e6xxx_config_prio(ds);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Configure the upstream port, and configure the upstream
> +	 * port as the port to which ingress and egress monitor frames
> +	 * are to be sent.
> +	 */
> +	if (REG_READ(REG_PORT(0), 0x03) == 0x1710)
> +		REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1111));
> +	else
> +		REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
> +
> +	/* Disable remote management for now, and set the switch's
> +	 * DSA device number.
> +	 */
> +	REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
> +
> +	/* Send all frames with destination addresses matching
> +	 * 01:80:c2:00:00:2x to the CPU port.
> +	 */
> +	REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
> +
> +	/* Send all frames with destination addresses matching
> +	 * 01:80:c2:00:00:0x to the CPU port.
> +	 */
> +	REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
> +
> +	/* Disable the loopback filter, disable flow control
> +	 * messages, disable flood broadcast override, disable
> +	 * removing of provider tags, disable ATU age violation
> +	 * interrupts, disable tag flow control, force flow
> +	 * control priority to the highest, and send all special
> +	 * multicast frames to the CPU at the highest priority.
> +	 */
> +	REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
> +
> +	/* Program the DSA routing table. */
> +	for (i = 0; i < 32; i++) {
> +		int nexthop;
> +
> +		nexthop = 0x1f;
> +		if (i != ds->index && i < ds->dst->pd->nr_chips)
> +			nexthop = ds->pd->rtable[i] & 0x1f;
> +
> +		REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
> +	}
> +
> +	/* Clear all trunk masks. */
> +	for (i = 0; i < 8; i++)
> +		REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
> +
> +	/* Clear all trunk mappings. */
> +	for (i = 0; i < 16; i++)
> +		REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
> +
> +	/* Disable ingress rate limiting by resetting all ingress
> +	 * rate limit registers to their initial state.
> +	 */
> +	for (i = 0; i < 6; i++)
> +		REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
> +
> +	/* Initialise cross-chip port VLAN table to reset defaults. */
> +	REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
> +
> +	/* Clear the priority override table. */
> +	for (i = 0; i < 16; i++)
> +		REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
> +
> +	/* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
> +
> +	return 0;
> +}
> +
> +static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
> +{
> +	int addr = REG_PORT(p);
> +	u16 val;
> +
> +	/* MAC Forcing register: don't force link, speed, duplex
> +	 * or flow control state to any particular values on physical
> +	 * ports, but force the CPU port and all DSA ports to 1000 Mb/s
> +	 * full duplex.
> +	 */
> +	val = REG_READ(addr, 0x01);
> +	if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
> +		REG_WRITE(addr, 0x01, val | 0x003e);
> +	else
> +		REG_WRITE(addr, 0x01, val | 0x0003);
> +
> +	/* Do not limit the period of time that this port can be
> +	 * paused for by the remote end or the period of time that
> +	 * this port can pause the remote end.
> +	 */
> +	REG_WRITE(addr, 0x02, 0x0000);
> +
> +	/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
> +	 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
> +	 * tunneling, determine priority by looking at 802.1p and IP
> +	 * priority fields (IP prio has precedence), and set STP state
> +	 * to Forwarding.
> +	 *
> +	 * If this is the CPU link, use DSA or EDSA tagging depending
> +	 * on which tagging mode was configured.
> +	 *
> +	 * If this is a link to another switch, use DSA tagging mode.
> +	 *
> +	 * If this is the upstream port for this switch, enable
> +	 * forwarding of unknown unicasts and multicasts.
> +	 */
> +	val = 0x0433;
> +	if (dsa_is_cpu_port(ds, p)) {
> +		if (ds->dst->tag_protocol == htons(ETH_P_EDSA))
> +			val |= 0x3300;
> +		else
> +			val |= 0x0100;
> +	}
> +	if (ds->dsa_port_mask & (1 << p))
> +		val |= 0x0100;
> +	if (p == dsa_upstream_port(ds))
> +		val |= 0x000c;
> +	REG_WRITE(addr, 0x04, val);
> +
> +	/* Port Control 1: disable trunking.  Also, if this is the
> +	 * CPU port, enable learn messages to be sent to this port.
> +	 */
> +	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
> +
> +	/* Port based VLAN map: give each port its own address
> +	 * database, allow the CPU port to talk to each of the 'real'
> +	 * ports, and allow each of the 'real' ports to only talk to
> +	 * the upstream port.
> +	 */
> +	val = (p & 0xf) << 12;
> +	if (dsa_is_cpu_port(ds, p))
> +		val |= ds->phys_port_mask;
> +	else
> +		val |= 1 << dsa_upstream_port(ds);
> +	REG_WRITE(addr, 0x06, val);
> +
> +	/* Default VLAN ID and priority: don't set a default VLAN
> +	 * ID, and set the default packet priority to zero.
> +	 */
> +	REG_WRITE(addr, 0x07, 0x0000);
> +
> +	/* Port Control 2: don't force a good FCS, set the maximum
> +	 * frame size to 10240 bytes, don't let the switch add or
> +	 * strip 802.1q tags, don't discard tagged or untagged frames
> +	 * on this port, do a destination address lookup on all
> +	 * received packets as usual, disable ARP mirroring and don't
> +	 * send a copy of all transmitted/received frames on this port
> +	 * to the CPU.
> +	 */
> +	REG_WRITE(addr, 0x08, 0x2080);
> +
> +	/* Egress rate control: disable egress rate control. */
> +	REG_WRITE(addr, 0x09, 0x0001);
> +
> +	/* Egress rate control 2: disable egress rate control. */
> +	REG_WRITE(addr, 0x0a, 0x0000);
> +
> +	/* Port Association Vector: when learning source addresses
> +	 * of packets, add the address to the address database using
> +	 * a port bitmap that has only the bit for this port set and
> +	 * the other bits clear.
> +	 */
> +	REG_WRITE(addr, 0x0b, 1 << p);
> +
> +	/* Port ATU control: disable limiting the number of address
> +	 * database entries that this port is allowed to use.
> +	 */
> +	REG_WRITE(addr, 0x0c, 0x0000);
> +
> +	/* Priority Override: disable DA, SA and VTU priority override. */
> +	REG_WRITE(addr, 0x0d, 0x0000);
> +
> +	/* Port Ethertype: use the Ethertype DSA Ethertype value. */
> +	REG_WRITE(addr, 0x0f, ETH_P_EDSA);
> +
> +	/* Tag Remap: use an identity 802.1p prio -> switch prio
> +	 * mapping.
> +	 */
> +	REG_WRITE(addr, 0x18, 0x3210);
> +
> +	/* Tag Remap 2: use an identity 802.1p prio -> switch prio
> +	 * mapping.
> +	 */
> +	REG_WRITE(addr, 0x19, 0x7654);
> +
> +	return 0;
> +}
> +
> +static int mv88e6171_setup(struct dsa_switch *ds)
> +{
> +	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
> +	int i;
> +	int ret;
> +
> +	mutex_init(&ps->smi_mutex);
> +	mutex_init(&ps->stats_mutex);
> +
> +	ret = mv88e6171_switch_reset(ds);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* @@@ initialise vtu and atu */
> +
> +	ret = mv88e6171_setup_global(ds);
> +	if (ret < 0)
> +		return ret;
> +
> +	for (i = 0; i < 8; i++) {
> +		if (!(dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i)))
> +			continue;
> +
> +		ret = mv88e6171_setup_port(ds, i);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mv88e6171_port_to_phy_addr(int port)
> +{
> +	if (port >= 0 && port <= 4)
> +		return port;
> +	return -1;
> +}
> +
> +static int
> +mv88e6171_phy_read(struct dsa_switch *ds, int port, int regnum)
> +{
> +	int addr = mv88e6171_port_to_phy_addr(port);
> +
> +	return mv88e6xxx_phy_read(ds, addr, regnum);
> +}
> +
> +static int
> +mv88e6171_phy_write(struct dsa_switch *ds,
> +		    int port, int regnum, u16 val)
> +{
> +	int addr = mv88e6171_port_to_phy_addr(port);
> +
> +	return mv88e6xxx_phy_write(ds, addr, regnum, val);
> +}
> +
> +static struct mv88e6xxx_hw_stat mv88e6171_hw_stats[] = {
> +	{ "in_good_octets", 8, 0x00, },
> +	{ "in_bad_octets", 4, 0x02, },
> +	{ "in_unicast", 4, 0x04, },
> +	{ "in_broadcasts", 4, 0x06, },
> +	{ "in_multicasts", 4, 0x07, },
> +	{ "in_pause", 4, 0x16, },
> +	{ "in_undersize", 4, 0x18, },
> +	{ "in_fragments", 4, 0x19, },
> +	{ "in_oversize", 4, 0x1a, },
> +	{ "in_jabber", 4, 0x1b, },
> +	{ "in_rx_error", 4, 0x1c, },
> +	{ "in_fcs_error", 4, 0x1d, },
> +	{ "out_octets", 8, 0x0e, },
> +	{ "out_unicast", 4, 0x10, },
> +	{ "out_broadcasts", 4, 0x13, },
> +	{ "out_multicasts", 4, 0x12, },
> +	{ "out_pause", 4, 0x15, },
> +	{ "excessive", 4, 0x11, },
> +	{ "collisions", 4, 0x1e, },
> +	{ "deferred", 4, 0x05, },
> +	{ "single", 4, 0x14, },
> +	{ "multiple", 4, 0x17, },
> +	{ "out_fcs_error", 4, 0x03, },
> +	{ "late", 4, 0x1f, },
> +	{ "hist_64bytes", 4, 0x08, },
> +	{ "hist_65_127bytes", 4, 0x09, },
> +	{ "hist_128_255bytes", 4, 0x0a, },
> +	{ "hist_256_511bytes", 4, 0x0b, },
> +	{ "hist_512_1023bytes", 4, 0x0c, },
> +	{ "hist_1024_max_bytes", 4, 0x0d, },
> +};
> +
> +static void
> +mv88e6171_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
> +{
> +	mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6171_hw_stats),
> +			      mv88e6171_hw_stats, port, data);
> +}
> +
> +static void
> +mv88e6171_get_ethtool_stats(struct dsa_switch *ds,
> +			    int port, uint64_t *data)
> +{
> +	mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6171_hw_stats),
> +				    mv88e6171_hw_stats, port, data);
> +}
> +
> +static int mv88e6171_get_sset_count(struct dsa_switch *ds)
> +{
> +	return ARRAY_SIZE(mv88e6171_hw_stats);
> +}
> +
> +struct dsa_switch_driver mv88e6171_switch_driver = {
> +	.tag_protocol		= cpu_to_be16(ETH_P_EDSA),
> +	.priv_size		= sizeof(struct mv88e6xxx_priv_state),
> +	.probe			= mv88e6171_probe,
> +	.setup			= mv88e6171_setup,
> +	.set_addr		= mv88e6xxx_set_addr_indirect,
> +	.phy_read		= mv88e6171_phy_read,
> +	.phy_write		= mv88e6171_phy_write,
> +	.poll_link		= mv88e6xxx_poll_link,
> +	.get_strings		= mv88e6171_get_strings,
> +	.get_ethtool_stats	= mv88e6171_get_ethtool_stats,
> +	.get_sset_count		= mv88e6171_get_sset_count,
> +};
> +
> +MODULE_ALIAS("platform:mv88e6171");
> diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
> index 9ce2146346b6..901d2a9704ef 100644
> --- a/drivers/net/dsa/mv88e6xxx.c
> +++ b/drivers/net/dsa/mv88e6xxx.c
> @@ -501,12 +501,18 @@ static int __init mv88e6xxx_init(void)
>  #if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
>  	register_switch_driver(&mv88e6123_61_65_switch_driver);
>  #endif
> +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
> +	register_switch_driver(&mv88e6171_switch_driver);
> +#endif
>  	return 0;
>  }
>  module_init(mv88e6xxx_init);
>  
>  static void __exit mv88e6xxx_cleanup(void)
>  {
> +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
> +	unregister_switch_driver(&mv88e6171_switch_driver);
> +#endif
>  #if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
>  	unregister_switch_driver(&mv88e6123_61_65_switch_driver);
>  #endif
> diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
> index 911ede58dd12..5e5145ad9525 100644
> --- a/drivers/net/dsa/mv88e6xxx.h
> +++ b/drivers/net/dsa/mv88e6xxx.h
> @@ -70,6 +70,7 @@ void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
>  
>  extern struct dsa_switch_driver mv88e6131_switch_driver;
>  extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
> +extern struct dsa_switch_driver mv88e6171_switch_driver;
>  
>  #define REG_READ(addr, reg)						\
>  	({								\
> 

^ permalink raw reply

* Re: [PATCH] net: axienet: remove unnecessary ether_setup after alloc_etherdev
From: David Miller @ 2014-09-12 22:16 UTC (permalink / raw)
  To: subbaraya.sundeep.bhatta
  Cc: jeffrey.t.kirsher, jesse.brandeburg, netdev, linux-kernel,
	michals, svemula, anirudh, sbhatta
In-Reply-To: <78ce1faf-0bf8-41bb-a30d-cecd11d82d94@BY2FFO11FD033.protection.gbl>

From: Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
Date: Thu, 11 Sep 2014 14:53:33 +0530

> calling ether_setup is redundant since alloc_etherdev calls
> it.
> 
> Signed-off-by: Subbaraya Sundeep Bhatta <sbhatta@xilinx.com>

Applied.

^ permalink raw reply

* Re: [PATCH v2 3/4] net: stmmac: add support for Intel Quark X1000
From: David Miller @ 2014-09-12 22:14 UTC (permalink / raw)
  To: hock.leong.kweh
  Cc: peppe.cavallaro, rayagond, vbridgers2013, srinivas.kandagatla,
	wens, netdev, linux-kernel, boon.leong.ong
In-Reply-To: <07ca9d2c89cf4f01037c98e3314dd035e4d2ee34.1410416224.git.hock.leong.kweh@intel.com>

From: Kweh Hock Leong <hock.leong.kweh@intel.com>
Date: Thu, 11 Sep 2014 16:38:39 +0800

> +		if ((!strcmp(quark_x1000_phy_info[i].board_name, board_name)) &&
> +		    quark_x1000_phy_info[i].pci_func_num == func_num)

It is entirely erroneous to identify a device by it's _PHYSICAL_ geographic
location on the PCI bus.

Please get rid of this PCI function number comparison and if necessary
find another means of identification.

^ permalink raw reply

* Re: [RFC] ipv4: Do not cache routing failures due to disabled forwarding.
From: Julian Anastasov @ 2014-09-12 22:13 UTC (permalink / raw)
  To: Nicolas Cavallari
  Cc: netdev, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy
In-Reply-To: <1410531260-13794-2-git-send-email-nicolas.cavallari@green-communications.fr>


	Hello,

On Fri, 12 Sep 2014, Nicolas Cavallari wrote:

> If we cache them, the kernel will reuse them, independently of
> whether forwarding is enabled or not.  Which means that if forwarding is
> disabled on the input interface where the first routing request comes
> from, then that unreachable result will be cached and reused for
> other interfaces, even if forwarding is enabled on them.
> 
> This can be verified with two interfaces A and B and an output interface
> C, where B has forwarding enabled, but not A and trying
> ip route get $dst iif A from $src && ip route get $dst iif B from $src

	Correct. While failed fib_lookup() does not set
res.fi in net/ipv4/fib_trie.c:check_leaf(), on fib_lookup()
success we have res.fi != NULL and it remains for the
!IN_DEV_FORWARD case (the 2nd 'goto no_route').

> Signed-off-by: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
> ---
> based on net-next, but not really tested on top of it.
> 
>  net/ipv4/route.c | 21 ++++++++++-----------
>  1 file changed, 10 insertions(+), 11 deletions(-)
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 234a43e..b537997 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -1655,7 +1655,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
>  	struct rtable	*rth;
>  	int		err = -EINVAL;
>  	struct net    *net = dev_net(dev);
> -	bool do_cache;
> +	bool do_cache = true;
>  
>  	/* IP on this device is disabled. */
>  
> @@ -1723,6 +1723,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
>  
>  	if (!IN_DEV_FORWARD(in_dev)) {
>  		err = -EHOSTUNREACH;
> +		do_cache = false;
>  		goto no_route;
>  	}
>  	if (res.type != RTN_UNICAST)
> @@ -1746,16 +1747,14 @@ brd_input:
>  	RT_CACHE_STAT_INC(in_brd);
>  
>  local_input:
> -	do_cache = false;
> -	if (res.fi) {
> -		if (!itag) {
> -			rth = rcu_dereference(FIB_RES_NH(res).nh_rth_input);
> -			if (rt_cache_valid(rth)) {
> -				skb_dst_set_noref(skb, &rth->dst);
> -				err = 0;
> -				goto out;
> -			}
> -			do_cache = true;
> +	if (!res.fi || itag) {
> +		do_cache = false;
> +	} else if (do_cache) {
> +		rth = rcu_dereference(FIB_RES_NH(res).nh_rth_input);
> +		if (rt_cache_valid(rth)) {
> +			skb_dst_set_noref(skb, &rth->dst);
> +			err = 0;
> +			goto out;
>  		}
>  	}
>  
> -- 
> 2.1.0

	Two alternatives are possible:

1. set res.fi = NULL after 'no_route:' label

or better

2. set do_cache = false after 'no_route:' label,
then instead of 'goto local_input;' jump to a new
label 'create_rt:' just before rt_dst_alloc.

	Not sure, they may generate less code in the fast path.

Regards

--
Julian Anastasov <ja@ssi.bg>

^ permalink raw reply

* [Patch v4 net-next 11/12] ARM: Documentation: Update fec dts binding doc
From: Frank.Li @ 2014-09-12 21:00 UTC (permalink / raw)
  To: b38611, davem, netdev, lznuaa
  Cc: shawn.guo, linux-arm-kernel, devicetree, linux, Frank Li,
	Fugang Duan
In-Reply-To: <1410555657-10744-1-git-send-email-Frank.Li@freescale.com>

From: Frank Li <Frank.Li@freescale.com>

    This patch update fec devicetree binding doc that add Optional
    properties "fsl,num-tx-queues" and "fsl,num-rx-queues".

Signed-off-by: Fugang Duan <B38611@freescale.com>
Signed-off-by: Frank Li <Frank.Li@freescale.com>
---
 Documentation/devicetree/bindings/net/fsl-fec.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 8a2c7b5..0c8775c 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -16,6 +16,12 @@ Optional properties:
 - phy-handle : phandle to the PHY device connected to this device.
 - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
   Use instead of phy-handle.
+- fsl,num-tx-queues : The property is valid for enet-avb IP, which supports
+  hw multi queues. Should specify the tx queue number, otherwise set tx queue
+  number to 1.
+- fsl,num-rx-queues : The property is valid for enet-avb IP, which supports
+  hw multi queues. Should specify the rx queue number, otherwise set rx queue
+  number to 1.
 
 Optional subnodes:
 - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
-- 
1.9.1

^ permalink raw reply related

* [Patch v4 net-next 10/12] net: fec: init complete variable in early to avoid kernel dump
From: Frank.Li @ 2014-09-12 21:00 UTC (permalink / raw)
  To: b38611, davem, netdev, lznuaa
  Cc: shawn.guo, linux-arm-kernel, devicetree, linux, Fugang Duan,
	Frank Li
In-Reply-To: <1410555657-10744-1-git-send-email-Frank.Li@freescale.com>

From: Fugang Duan <B38611@freescale.com>

Software clear the MDIO interrupt before MDIO bus access, but
MAC still generate MDIO interrupt. The issue only happen on
imx6slx chip.

CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.17.0-rc1-00399-g0bcad17 #315
Backtrace:
[<800121fc>] (dump_backtrace) from [<800124e0>] (show_stack+0x18/0x1c)
 r6:8096e534 r5:8096e534 r4:00000000 r3:00000000
[<800124c8>] (show_stack) from [<806a4c60>] (dump_stack+0x8c/0xa4)
[<806a4bd4>] (dump_stack) from [<80060ab8>] (__lock_acquire+0x1814/0x1c40)
 r6:be078000 r5:be074000 r4:be03f6e4 r3:be078000
[<8005f2a4>] (__lock_acquire) from [<800616e0>] (lock_acquire+0x70/0x84)
 r10:809ada33 r9:be010600 r8:00000096 r7:00000001 r6:be074000 r5:00000000
 r4:60000193
[<80061670>] (lock_acquire) from [<806abb20>] (_raw_spin_lock_irqsave+0x40/0x54)
 r7:00000000 r6:8005a3f8 r5:00000193 r4:be03f6d4
[<806abae0>] (_raw_spin_lock_irqsave) from [<8005a3f8>] (complete+0x1c/0x4c)
 r6:80950904 r5:be03f6d0 r4:be03f6d4
[<8005a3dc>] (complete) from [<8041b4c0>] (fec_enet_interrupt+0x128/0x164)
 r6:80950904 r5:00800000 r4:be03f000 r3:00000000
[<8041b398>] (fec_enet_interrupt) from [<8006aeac>] (handle_irq_event_percpu+0x38/0x13c)
 r6:00000000 r5:be01065c r4:be399e00 r3:8041b398
[<8006ae74>] (handle_irq_event_percpu) from [<8006aff4>] (handle_irq_event+0x44/0x64)
 r10:be03f000 r9:80989fe0 r8:00000000 r7:00000096 r6:be399e00 r5:be01065c
 r4:be010600
[<8006afb0>] (handle_irq_event) from [<8006e3e8>] (handle_fasteoi_irq+0xc8/0x1bc)
 r6:8096e764 r5:be01065c r4:be010600 r3:00000000
[<8006e320>] (handle_fasteoi_irq) from [<8006a63c>] (generic_handle_irq+0x30/0x44)
 r6:be074010 r5:80945e4c r4:00000096 r3:8006e320
[<8006a60c>] (generic_handle_irq) from [<8000f218>] (handle_IRQ+0x54/0xbc)
 r4:80950d74 r3:00000180
[<8000f1c4>] (handle_IRQ) from [<800086cc>] (gic_handle_irq+0x30/0x68)
 r8:be3ab478 r7:c080e100 r6:be075bd8 r5:80950eec r4:c080e10c r3:000000a0
[<8000869c>] (gic_handle_irq) from [<80013064>] (__irq_svc+0x44/0x5c)

Signed-off-by: Fugang Duan <B38611@freescale.com>
Signed-off-by: Frank Li <Frank.Li@freescale.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9840a10..8f8e55e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3066,6 +3066,7 @@ fec_probe(struct platform_device *pdev)
 			goto failed_irq;
 	}
 
+	init_completion(&fep->mdio_done);
 	ret = fec_enet_mii_init(pdev);
 	if (ret)
 		goto failed_mii_init;
-- 
1.9.1

^ permalink raw reply related

* [PATCH] net: DSA: Marvell mv88e6171 switch driver
From: Andrew Lunn @ 2014-09-12 21:58 UTC (permalink / raw)
  To: davem; +Cc: f.fainelli, netdev, Andrew Lunn, Claudio Leite

This is the Marvell driver with some cleanups by Claudio Leite
and myself.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Cc: Claudio Leite <leitec@staticky.com>
---
 drivers/net/dsa/Kconfig     |   9 +
 drivers/net/dsa/Makefile    |   3 +
 drivers/net/dsa/mv88e6171.c | 407 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx.c |   6 +
 drivers/net/dsa/mv88e6xxx.h |   1 +
 5 files changed, 426 insertions(+)
 create mode 100644 drivers/net/dsa/mv88e6171.c

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index c6ee07c6a1b5..ea0697eaeff5 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -36,6 +36,15 @@ config NET_DSA_MV88E6123_61_65
 	  This enables support for the Marvell 88E6123/6161/6165
 	  ethernet switch chips.
 
+config NET_DSA_MV88E6171
+	tristate "Marvell 88E6171 ethernet switch chip support"
+	select NET_DSA
+	select NET_DSA_MV88E6XXX
+	select NET_DSA_TAG_EDSA
+	---help---
+	  This enables support for the Marvell 88E6171 ethernet switch
+	  chip.
+
 config NET_DSA_BCM_SF2
 	tristate "Broadcom Starfighter 2 Ethernet switch support"
 	select NET_DSA
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index dd3cd3b8157f..23a90de9830e 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -7,4 +7,7 @@ endif
 ifdef CONFIG_NET_DSA_MV88E6131
 mv88e6xxx_drv-y += mv88e6131.o
 endif
+ifdef CONFIG_NET_DSA_MV88E6171
+mv88e6xxx_drv-y += mv88e6171.o
+endif
 obj-$(CONFIG_NET_DSA_BCM_SF2)	+= bcm_sf2.o
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
new file mode 100644
index 000000000000..8bae73bec1d7
--- /dev/null
+++ b/drivers/net/dsa/mv88e6171.c
@@ -0,0 +1,407 @@
+/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
+ * Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <net/dsa.h>
+#include "mv88e6xxx.h"
+
+static char *mv88e6171_probe(struct mii_bus *bus, int sw_addr)
+{
+	int ret;
+
+	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
+	if (ret >= 0) {
+		if ((ret & 0xfff0) == 0x1710)
+			return "Marvell 88E6171";
+	}
+
+	return NULL;
+}
+
+static int mv88e6171_switch_reset(struct dsa_switch *ds)
+{
+	int i;
+	int ret;
+	unsigned long timeout;
+
+	/* Set all ports to the disabled state. */
+	for (i = 0; i < 8; i++) {
+		ret = REG_READ(REG_PORT(i), 0x04);
+		REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
+	}
+
+	/* Wait for transmit queues to drain. */
+	usleep_range(2000, 4000);
+
+	/* Reset the switch. */
+	REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
+
+	/* Wait up to one second for reset to complete. */
+	timeout = jiffies + 1 * HZ;
+	while (time_before(jiffies, timeout)) {
+		ret = REG_READ(REG_GLOBAL, 0x00);
+		if ((ret & 0xc800) == 0xc800)
+			break;
+
+		usleep_range(1000, 2000);
+	}
+	if (time_after(jiffies, timeout))
+		return -ETIMEDOUT;
+
+	/* Enable ports not under DSA, e.g. WAN port */
+	for (i = 0; i < 8; i++) {
+		if (dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i))
+			continue;
+
+		ret = REG_READ(REG_PORT(i), 0x04);
+		REG_WRITE(REG_PORT(i), 0x04, ret | 0x03);
+	}
+
+	return 0;
+}
+
+static int mv88e6171_setup_global(struct dsa_switch *ds)
+{
+	int ret;
+	int i;
+
+	/* Disable the PHY polling unit (since there won't be any
+	 * external PHYs to poll), don't discard packets with
+	 * excessive collisions, and mask all interrupt sources.
+	 */
+	REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
+
+	/* Set the default address aging time to 5 minutes, and
+	 * enable address learn messages to be sent to all message
+	 * ports.
+	 */
+	REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
+
+	/* Configure the priority mapping registers. */
+	ret = mv88e6xxx_config_prio(ds);
+	if (ret < 0)
+		return ret;
+
+	/* Configure the upstream port, and configure the upstream
+	 * port as the port to which ingress and egress monitor frames
+	 * are to be sent.
+	 */
+	if (REG_READ(REG_PORT(0), 0x03) == 0x1710)
+		REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1111));
+	else
+		REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
+
+	/* Disable remote management for now, and set the switch's
+	 * DSA device number.
+	 */
+	REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
+
+	/* Send all frames with destination addresses matching
+	 * 01:80:c2:00:00:2x to the CPU port.
+	 */
+	REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
+
+	/* Send all frames with destination addresses matching
+	 * 01:80:c2:00:00:0x to the CPU port.
+	 */
+	REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
+
+	/* Disable the loopback filter, disable flow control
+	 * messages, disable flood broadcast override, disable
+	 * removing of provider tags, disable ATU age violation
+	 * interrupts, disable tag flow control, force flow
+	 * control priority to the highest, and send all special
+	 * multicast frames to the CPU at the highest priority.
+	 */
+	REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
+
+	/* Program the DSA routing table. */
+	for (i = 0; i < 32; i++) {
+		int nexthop;
+
+		nexthop = 0x1f;
+		if (i != ds->index && i < ds->dst->pd->nr_chips)
+			nexthop = ds->pd->rtable[i] & 0x1f;
+
+		REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
+	}
+
+	/* Clear all trunk masks. */
+	for (i = 0; i < 8; i++)
+		REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
+
+	/* Clear all trunk mappings. */
+	for (i = 0; i < 16; i++)
+		REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
+
+	/* Disable ingress rate limiting by resetting all ingress
+	 * rate limit registers to their initial state.
+	 */
+	for (i = 0; i < 6; i++)
+		REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
+
+	/* Initialise cross-chip port VLAN table to reset defaults. */
+	REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
+
+	/* Clear the priority override table. */
+	for (i = 0; i < 16; i++)
+		REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
+
+	/* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
+
+	return 0;
+}
+
+static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
+{
+	int addr = REG_PORT(p);
+	u16 val;
+
+	/* MAC Forcing register: don't force link, speed, duplex
+	 * or flow control state to any particular values on physical
+	 * ports, but force the CPU port and all DSA ports to 1000 Mb/s
+	 * full duplex.
+	 */
+	val = REG_READ(addr, 0x01);
+	if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
+		REG_WRITE(addr, 0x01, val | 0x003e);
+	else
+		REG_WRITE(addr, 0x01, val | 0x0003);
+
+	/* Do not limit the period of time that this port can be
+	 * paused for by the remote end or the period of time that
+	 * this port can pause the remote end.
+	 */
+	REG_WRITE(addr, 0x02, 0x0000);
+
+	/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
+	 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
+	 * tunneling, determine priority by looking at 802.1p and IP
+	 * priority fields (IP prio has precedence), and set STP state
+	 * to Forwarding.
+	 *
+	 * If this is the CPU link, use DSA or EDSA tagging depending
+	 * on which tagging mode was configured.
+	 *
+	 * If this is a link to another switch, use DSA tagging mode.
+	 *
+	 * If this is the upstream port for this switch, enable
+	 * forwarding of unknown unicasts and multicasts.
+	 */
+	val = 0x0433;
+	if (dsa_is_cpu_port(ds, p)) {
+		if (ds->dst->tag_protocol == htons(ETH_P_EDSA))
+			val |= 0x3300;
+		else
+			val |= 0x0100;
+	}
+	if (ds->dsa_port_mask & (1 << p))
+		val |= 0x0100;
+	if (p == dsa_upstream_port(ds))
+		val |= 0x000c;
+	REG_WRITE(addr, 0x04, val);
+
+	/* Port Control 1: disable trunking.  Also, if this is the
+	 * CPU port, enable learn messages to be sent to this port.
+	 */
+	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
+
+	/* Port based VLAN map: give each port its own address
+	 * database, allow the CPU port to talk to each of the 'real'
+	 * ports, and allow each of the 'real' ports to only talk to
+	 * the upstream port.
+	 */
+	val = (p & 0xf) << 12;
+	if (dsa_is_cpu_port(ds, p))
+		val |= ds->phys_port_mask;
+	else
+		val |= 1 << dsa_upstream_port(ds);
+	REG_WRITE(addr, 0x06, val);
+
+	/* Default VLAN ID and priority: don't set a default VLAN
+	 * ID, and set the default packet priority to zero.
+	 */
+	REG_WRITE(addr, 0x07, 0x0000);
+
+	/* Port Control 2: don't force a good FCS, set the maximum
+	 * frame size to 10240 bytes, don't let the switch add or
+	 * strip 802.1q tags, don't discard tagged or untagged frames
+	 * on this port, do a destination address lookup on all
+	 * received packets as usual, disable ARP mirroring and don't
+	 * send a copy of all transmitted/received frames on this port
+	 * to the CPU.
+	 */
+	REG_WRITE(addr, 0x08, 0x2080);
+
+	/* Egress rate control: disable egress rate control. */
+	REG_WRITE(addr, 0x09, 0x0001);
+
+	/* Egress rate control 2: disable egress rate control. */
+	REG_WRITE(addr, 0x0a, 0x0000);
+
+	/* Port Association Vector: when learning source addresses
+	 * of packets, add the address to the address database using
+	 * a port bitmap that has only the bit for this port set and
+	 * the other bits clear.
+	 */
+	REG_WRITE(addr, 0x0b, 1 << p);
+
+	/* Port ATU control: disable limiting the number of address
+	 * database entries that this port is allowed to use.
+	 */
+	REG_WRITE(addr, 0x0c, 0x0000);
+
+	/* Priority Override: disable DA, SA and VTU priority override. */
+	REG_WRITE(addr, 0x0d, 0x0000);
+
+	/* Port Ethertype: use the Ethertype DSA Ethertype value. */
+	REG_WRITE(addr, 0x0f, ETH_P_EDSA);
+
+	/* Tag Remap: use an identity 802.1p prio -> switch prio
+	 * mapping.
+	 */
+	REG_WRITE(addr, 0x18, 0x3210);
+
+	/* Tag Remap 2: use an identity 802.1p prio -> switch prio
+	 * mapping.
+	 */
+	REG_WRITE(addr, 0x19, 0x7654);
+
+	return 0;
+}
+
+static int mv88e6171_setup(struct dsa_switch *ds)
+{
+	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
+	int i;
+	int ret;
+
+	mutex_init(&ps->smi_mutex);
+	mutex_init(&ps->stats_mutex);
+
+	ret = mv88e6171_switch_reset(ds);
+	if (ret < 0)
+		return ret;
+
+	/* @@@ initialise vtu and atu */
+
+	ret = mv88e6171_setup_global(ds);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < 8; i++) {
+		if (!(dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i)))
+			continue;
+
+		ret = mv88e6171_setup_port(ds, i);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mv88e6171_port_to_phy_addr(int port)
+{
+	if (port >= 0 && port <= 4)
+		return port;
+	return -1;
+}
+
+static int
+mv88e6171_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+	int addr = mv88e6171_port_to_phy_addr(port);
+
+	return mv88e6xxx_phy_read(ds, addr, regnum);
+}
+
+static int
+mv88e6171_phy_write(struct dsa_switch *ds,
+		    int port, int regnum, u16 val)
+{
+	int addr = mv88e6171_port_to_phy_addr(port);
+
+	return mv88e6xxx_phy_write(ds, addr, regnum, val);
+}
+
+static struct mv88e6xxx_hw_stat mv88e6171_hw_stats[] = {
+	{ "in_good_octets", 8, 0x00, },
+	{ "in_bad_octets", 4, 0x02, },
+	{ "in_unicast", 4, 0x04, },
+	{ "in_broadcasts", 4, 0x06, },
+	{ "in_multicasts", 4, 0x07, },
+	{ "in_pause", 4, 0x16, },
+	{ "in_undersize", 4, 0x18, },
+	{ "in_fragments", 4, 0x19, },
+	{ "in_oversize", 4, 0x1a, },
+	{ "in_jabber", 4, 0x1b, },
+	{ "in_rx_error", 4, 0x1c, },
+	{ "in_fcs_error", 4, 0x1d, },
+	{ "out_octets", 8, 0x0e, },
+	{ "out_unicast", 4, 0x10, },
+	{ "out_broadcasts", 4, 0x13, },
+	{ "out_multicasts", 4, 0x12, },
+	{ "out_pause", 4, 0x15, },
+	{ "excessive", 4, 0x11, },
+	{ "collisions", 4, 0x1e, },
+	{ "deferred", 4, 0x05, },
+	{ "single", 4, 0x14, },
+	{ "multiple", 4, 0x17, },
+	{ "out_fcs_error", 4, 0x03, },
+	{ "late", 4, 0x1f, },
+	{ "hist_64bytes", 4, 0x08, },
+	{ "hist_65_127bytes", 4, 0x09, },
+	{ "hist_128_255bytes", 4, 0x0a, },
+	{ "hist_256_511bytes", 4, 0x0b, },
+	{ "hist_512_1023bytes", 4, 0x0c, },
+	{ "hist_1024_max_bytes", 4, 0x0d, },
+};
+
+static void
+mv88e6171_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
+{
+	mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6171_hw_stats),
+			      mv88e6171_hw_stats, port, data);
+}
+
+static void
+mv88e6171_get_ethtool_stats(struct dsa_switch *ds,
+			    int port, uint64_t *data)
+{
+	mv88e6xxx_get_ethtool_stats(ds, ARRAY_SIZE(mv88e6171_hw_stats),
+				    mv88e6171_hw_stats, port, data);
+}
+
+static int mv88e6171_get_sset_count(struct dsa_switch *ds)
+{
+	return ARRAY_SIZE(mv88e6171_hw_stats);
+}
+
+struct dsa_switch_driver mv88e6171_switch_driver = {
+	.tag_protocol		= cpu_to_be16(ETH_P_EDSA),
+	.priv_size		= sizeof(struct mv88e6xxx_priv_state),
+	.probe			= mv88e6171_probe,
+	.setup			= mv88e6171_setup,
+	.set_addr		= mv88e6xxx_set_addr_indirect,
+	.phy_read		= mv88e6171_phy_read,
+	.phy_write		= mv88e6171_phy_write,
+	.poll_link		= mv88e6xxx_poll_link,
+	.get_strings		= mv88e6171_get_strings,
+	.get_ethtool_stats	= mv88e6171_get_ethtool_stats,
+	.get_sset_count		= mv88e6171_get_sset_count,
+};
+
+MODULE_ALIAS("platform:mv88e6171");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 9ce2146346b6..901d2a9704ef 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -501,12 +501,18 @@ static int __init mv88e6xxx_init(void)
 #if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
 	register_switch_driver(&mv88e6123_61_65_switch_driver);
 #endif
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
+	register_switch_driver(&mv88e6171_switch_driver);
+#endif
 	return 0;
 }
 module_init(mv88e6xxx_init);
 
 static void __exit mv88e6xxx_cleanup(void)
 {
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
+	unregister_switch_driver(&mv88e6171_switch_driver);
+#endif
 #if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
 	unregister_switch_driver(&mv88e6123_61_65_switch_driver);
 #endif
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 911ede58dd12..5e5145ad9525 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -70,6 +70,7 @@ void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
 
 extern struct dsa_switch_driver mv88e6131_switch_driver;
 extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
+extern struct dsa_switch_driver mv88e6171_switch_driver;
 
 #define REG_READ(addr, reg)						\
 	({								\
-- 
2.1.0

^ permalink raw reply related

* [Patch v4 net-next 04/12] net: fec: parser max queue number from dt file
From: Frank.Li @ 2014-09-12 21:00 UTC (permalink / raw)
  To: b38611, davem, netdev, lznuaa
  Cc: shawn.guo, linux-arm-kernel, devicetree, linux, Fugang Duan,
	Frank Li
In-Reply-To: <1410555657-10744-1-git-send-email-Frank.Li@freescale.com>

From: Fugang Duan <B38611@freescale.com>

By default, the tx/rx queue number is 1, user can config the queue number
at DTS file like this:
	fsl,num-tx-queues=<3>;
	fsl,num-rx-queues=<3>

Since i.MX6SX enet-AVB IP support multi queues, so use multi queues
interface to allocate and set up an Ethernet device.

Signed-off-by: Fugang Duan <B38611@freescale.com>
Signed-off-by: Frank Li <Frank.Li@freescale.com>
---
 drivers/net/ethernet/freescale/fec.h      |  2 ++
 drivers/net/ethernet/freescale/fec_main.c | 46 ++++++++++++++++++++++++++++++-
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index b2b91f8..72fb90f 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -356,6 +356,8 @@ struct fec_enet_private {
 
 	bool ptp_clk_on;
 	struct mutex ptp_clk_mutex;
+	unsigned int num_tx_queues;
+	unsigned int num_rx_queues;
 
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	struct fec_enet_priv_tx_q *tx_queue[FEC_ENET_MAX_TX_QS];
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 4c0d2ee..2240df0 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2709,6 +2709,42 @@ static void fec_reset_phy(struct platform_device *pdev)
 }
 #endif /* CONFIG_OF */
 
+static void
+fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int err;
+
+	*num_tx = *num_rx = 1;
+
+	if (!np || !of_device_is_available(np))
+		return;
+
+	/* parse the num of tx and rx queues */
+	err = of_property_read_u32(np, "fsl,num-tx-queues", num_tx);
+	err |= of_property_read_u32(np, "fsl,num-rx-queues", num_rx);
+	if (err) {
+		*num_tx = 1;
+		*num_rx = 1;
+		return;
+	}
+
+	if (*num_tx < 1 || *num_tx > FEC_ENET_MAX_TX_QS) {
+		dev_err(&pdev->dev, "Invalidate num_tx(=%d), fail back to 1\n",
+			*num_tx);
+		*num_tx = 1;
+		return;
+	}
+
+	if (*num_rx < 1 || *num_rx > FEC_ENET_MAX_RX_QS) {
+		dev_err(&pdev->dev, "Invalidate num_rx(=%d), fail back to 1\n",
+			*num_rx);
+		*num_rx = 1;
+		return;
+	}
+
+}
+
 static int
 fec_probe(struct platform_device *pdev)
 {
@@ -2720,13 +2756,18 @@ fec_probe(struct platform_device *pdev)
 	const struct of_device_id *of_id;
 	static int dev_id;
 	struct device_node *np = pdev->dev.of_node, *phy_node;
+	int num_tx_qs = 1;
+	int num_rx_qs = 1;
 
 	of_id = of_match_device(fec_dt_ids, &pdev->dev);
 	if (of_id)
 		pdev->id_entry = of_id->data;
 
+	fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
+
 	/* Init network device */
-	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
+	ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private),
+				  num_tx_qs, num_rx_qs);
 	if (!ndev)
 		return -ENOMEM;
 
@@ -2735,6 +2776,9 @@ fec_probe(struct platform_device *pdev)
 	/* setup board info structure */
 	fep = netdev_priv(ndev);
 
+	fep->num_rx_queues = num_rx_qs;
+	fep->num_tx_queues = num_tx_qs;
+
 #if !defined(CONFIG_M5272)
 	/* default enable pause frame auto negotiation */
 	if (pdev->id_entry &&
-- 
1.9.1

^ permalink raw reply related

* [Patch v4 net-next 00/12] net: fec: imx6sx multiqueue support
From: Frank.Li @ 2014-09-12 21:00 UTC (permalink / raw)
  To: b38611, davem, netdev, lznuaa
  Cc: shawn.guo, linux-arm-kernel, devicetree, linux, Frank Li

From: Frank Li <Frank.Li@freescale.com>

These patches enable i.MX6SX multi queue support.
i.MX6SX support 3 queue and AVB feature.

Change from v3 to v4
 - use "unsigned int" instead of "unsigned"

Change from v2 to v3
 - fixed alignment requirement for ARM and NO-ARM platform

Change from v1 to v2.
 - Change num_tx_queue to unsigned int
 - Avoid block non-dt platform
 - remove call netif_set_real_num_rx_queues
 - seperate multi queue patch two part, one is tx and rx handle, with fixed queue 0
   then other one is initilized multiqueue
 - use two difference alignment for tx and rx path

Frank Li (4):
  net: fec: init multi queue date structure
  net: fec: add enet-avb IP support
  ARM: Documentation: Update fec dts binding doc
  ARM: dts: imx6sx: add multi-queue support enet

Fugang Duan (8):
  net:fec: add enet refrence clock for i.MX 6SX chip
  net:fec: add enet AVB feature macro define for imx6sx
  net: fec: change data structure to support multiqueue
  net: fec: parser max queue number from dt file
  net:fec: Disable enet-avb MAC instead of reset MAC
  net:fec: Add fsl,imx6sx-fec  compatible strings
  net: fec: change FEC alignment according to i.mx6 sx requirement
  net: fec: init complete variable in early to avoid kernel dump

 Documentation/devicetree/bindings/net/fsl-fec.txt |   6 +
 arch/arm/boot/dts/imx6sx.dtsi                     |   2 +
 drivers/net/ethernet/freescale/fec.h              | 154 +++-
 drivers/net/ethernet/freescale/fec_main.c         | 853 ++++++++++++++++------
 4 files changed, 756 insertions(+), 259 deletions(-)

-- 
1.9.1

^ permalink raw reply

* Re: pull-request: can 2014-09-11
From: David Miller @ 2014-09-12 22:05 UTC (permalink / raw)
  To: mkl; +Cc: netdev, linux-can, kernel
In-Reply-To: <1410421984-15125-1-git-send-email-mkl@pengutronix.de>

From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: Thu, 11 Sep 2014 09:53:03 +0200

> this is a pull request for the current release cycle of a single patch.
> 
> The patch by David Jander fixes a scheduling while atomic problem in the
> flexcan driver, that was introduced by me in v3.14-rc6.
 ...
>   git://gitorious.org/linux-can/linux-can.git tags/linux-can-fixes-for-3.17-20140911

Pulled, thanks Marc.

^ permalink raw reply

* Re: [PATCH net-next] ethernet: amd: use pr_info_once()
From: David Miller @ 2014-09-12 22:03 UTC (permalink / raw)
  To: varkabhadram; +Cc: netdev, Thomas.Lendacky, varkab
In-Reply-To: <1410420050-16088-1-git-send-email-varkab@cdac.in>

From: Varka Bhadram <varkabhadram@gmail.com>
Date: Thu, 11 Sep 2014 12:50:50 +0530

> It will use pr_info_one() to print the version info of the
> driver in probe function only once. No need to use the static
> variable here.
> 
> Signed-off-by: Varka Bhadram <varkab@cdac.in>

Applied, thank you.

^ permalink raw reply

* Re: [PATCH] udp: Fix inverted NAPI_GRO_CB(skb)->flush test
From: David Miller @ 2014-09-12 21:55 UTC (permalink / raw)
  To: scottwood; +Cc: netdev, therbert
In-Reply-To: <1410402198-30811-1-git-send-email-scottwood@freescale.com>

From: Scott Wood <scottwood@freescale.com>
Date: Wed, 10 Sep 2014 21:23:18 -0500

> Commit 2abb7cdc0d ("udp: Add support for doing checksum unnecessary
> conversion") caused napi_gro_cb structs with the "flush" field zero to
> take the "udp_gro_receive" path rather than the "set flush to 1" path
> that they would previously take.  As a result I saw booting from an NFS
> root hang shortly after starting userspace, with "server not
> responding" messages.
> 
> This change to the handling of "flush == 0" packets appears to be
> incidental to the goal of adding new code in the case where
> skb_gro_checksum_validate_zero_check() returns zero.  Based on that and
> the fact that it breaks things, I'm assuming that it is unintentional.
> 
> Fixes: 2abb7cdc0d ("udp: Add support for doing checksum unnecessary conversion")
> Cc: Tom Herbert <therbert@google.com>
> Signed-off-by: Scott Wood <scottwood@freescale.com>

Applied, thank you.

^ permalink raw reply

* Re: [PATCH 1/3] virtio_net: pass well-formed sgs to virtqueue_add_*()
From: David Miller @ 2014-09-12 21:54 UTC (permalink / raw)
  To: rusty; +Cc: linux-kernel, netdev, mst
In-Reply-To: <1410396458-1165-2-git-send-email-rusty@rustcorp.com.au>


Do you guys want me to take this series directly into net-next?

^ permalink raw reply

* Re: [PATCH] pktgen: nowait parameter.
From: David Miller @ 2014-09-12 21:52 UTC (permalink / raw)
  To: rusty; +Cc: netdev, brouer, minipli
In-Reply-To: <871trjjbd2.fsf@rustcorp.com.au>

From: Rusty Russell <rusty@rustcorp.com.au>
Date: Thu, 11 Sep 2014 09:07:29 +0930

> David Miller <davem@davemloft.net> writes:
>> From: Rusty Russell <rusty@rustcorp.com.au>
>> Date: Wed, 03 Sep 2014 13:50:01 +0930
>>
>> BTW, wrt. holding onto TX frames for unbounded amounts of time, I
>> think this is a bad idea even with skb_orphan().  There are resources
>> from the SKB you are hanging onto which can stall the removal of
>> modules indefinitely, such as netfilter references.
> 
> We could certainly have a once-a-second timer which did this, but should
> skb_orphan() do that work instead?

It would definitely improve the situation.

I've discussed a few times with Herbert Xu the idea of using hrtimers
since we have those, to do something more clever and timely.

^ permalink raw reply

* Re: [PATCH net-next 0/2] Address reference counting issues with sock_queue_err_skb
From: David Miller @ 2014-09-12 21:51 UTC (permalink / raw)
  To: alexander.h.duyck
  Cc: netdev, linux-wireless, johannes, eric.dumazet, linville
In-Reply-To: <20140910215837.23225.39149.stgit@ahduyck-bv4.jf.intel.com>

From: Alexander Duyck <alexander.h.duyck@intel.com>
Date: Wed, 10 Sep 2014 18:04:42 -0400

> After looking over the code for skb_clone_sk after some comments made by
> Eric Dumazet I have come to the conclusion that skb_clone_sk is taking the
> correct approach in how to handle the sk_refcnt when creating a buffer that
> is eventually meant to be returned to the socket via the sock_queue_err_skb
> function.
> 
> However upon review of other callers I found what I believe to be a
> possible reference count issue in the path for handling "wifi ack" packets.
> To address this I have applied the same logic that is currently in place so
> that the sk_refcnt will be forced to stay at least 1, or we will not
> provide an skb to return in the sk_error_queue.

Series applied, thanks Alex.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox