Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] tipc: set sk_err correctly when connection fails
From: Ying Xue @ 2013-08-27  0:45 UTC (permalink / raw)
  To: erik.hugne; +Cc: netdev, jon.maloy, paul.gortmaker, tipc-discussion, nhan.tt.vo
In-Reply-To: <1377266200-26691-1-git-send-email-erik.hugne@ericsson.com>

On 08/23/2013 09:56 PM, erik.hugne@ericsson.com wrote:
> From: Erik Hugne <erik.hugne@ericsson.com>
> 
> This fixes a problem when connect() fails and returns the error
> code as a positive value, whereas errno itself is never set. The
> reason is that error codes set in sk_err should never be inverted.
> 
> Signed-off-by: Erik Hugne <erik.hugne@ericsson.com>

Acked-by: Ying Xue <ying.xue@windriver.com>

> ---
>  net/tipc/socket.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> index ce8249c..6cc7ddd 100644
> --- a/net/tipc/socket.c
> +++ b/net/tipc/socket.c
> @@ -1257,7 +1257,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
>  		/* Accept only ACK or NACK message */
>  		if (unlikely(msg_errcode(msg))) {
>  			sock->state = SS_DISCONNECTING;
> -			sk->sk_err = -ECONNREFUSED;
> +			sk->sk_err = ECONNREFUSED;
>  			retval = TIPC_OK;
>  			break;
>  		}
> @@ -1268,7 +1268,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
>  		res = auto_connect(sock, msg);
>  		if (res) {
>  			sock->state = SS_DISCONNECTING;
> -			sk->sk_err = res;
> +			sk->sk_err = -res;
>  			retval = TIPC_OK;
>  			break;
>  		}
> 

^ permalink raw reply

* Re: [PATCH net-next] pkt_sched: fq: Fair Queue packet scheduler
From: Eric Dumazet @ 2013-08-27  0:45 UTC (permalink / raw)
  To: Vijay Subramanian; +Cc: netdev
In-Reply-To: <CAGK4HS_9cwEFdifYpe4Lq+daH2dzgaXCYOBNA+rkAnYw=imvfg@mail.gmail.com>

On Mon, 2013-08-26 at 17:28 -0700, Vijay Subramanian wrote:
> (Resending this as my earlier email to netdev bounced).
> 
>  On 24 August 2013 23:53, David Miller <davem@davemloft.net> wrote:
> >
> >
> > This depends upon your TCP patch, I knew this but you really should
> > be explicit about dependencies. :-)
> 
> Eric,
> If you are planning to resend this patch, you may want to take care of
> some trailing space issues reported by checkpatch plus some other
> warnings.

Thanks, will do ;)

^ permalink raw reply

* Re: [PATCH net-next] pkt_sched: fq: Fair Queue packet scheduler
From: Vijay Subramanian @ 2013-08-27  0:28 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <CAGK4HS9T_aXJiSDaTbPfX92Z6Cqo7+EcS-k5jh6oc65yA5bf5A@mail.gmail.com>

(Resending this as my earlier email to netdev bounced).

 On 24 August 2013 23:53, David Miller <davem@davemloft.net> wrote:
>
>
> This depends upon your TCP patch, I knew this but you really should
> be explicit about dependencies. :-)

Eric,
If you are planning to resend this patch, you may want to take care of
some trailing space issues reported by checkpatch plus some other
warnings.

Applying: pkt_sched: fq: Fair Queue packet scheduler
/usr/src/net-next/.git/rebase-apply/patch:555: trailing whitespace.
/usr/src/net-next/.git/rebase-apply/patch:613: trailing whitespace.
/usr/src/net-next/.git/rebase-apply/patch:751: trailing whitespace.
}
/usr/src/net-next/.git/rebase-apply/patch:755: trailing whitespace.
qdisc_watchdog_cancel(&q->watchdog);
/usr/src/net-next/.git/rebase-apply/patch:821: trailing whitespace.


Thanks,
Vijay

^ permalink raw reply

* Re: pcie_get_minimum_link returns 0 width
From: Bjorn Helgaas @ 2013-08-26 23:57 UTC (permalink / raw)
  To: Yuval Mintz
  Cc: jacob.e.keller@intel.com, linux-pci@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <979A8436335E3744ADCD3A9F2A2B68A52AD13D0C@SJEXCHMB10.corp.ad.broadcom.com>

On Mon, Aug 26, 2013 at 5:36 PM, Yuval Mintz <yuvalmin@broadcom.com> wrote:
>> > Hi,
>> >
>> > I tried adding support for the newly added 'pcie_get_minimum_link' into
>> the
>> > bnx2x driver, but found out the some of my devices started showing width
>> x0.
>> >
>> > By adding debug prints, I've found out there were devices up the chain that
>> > Showed 0 when their PCI_EXP_LNKSTA was read by said function.
>> > However, when I tried looking via lspci the output claimed the width was
>> x4.
>>
>> I don't see a 'pcie_get_minimum_link()' function in my current tree
>> (git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git "next"
>> branch).  Maybe seeing your patch (with the debug prints) would give
>> me a hook for somewhere to start looking.
>
> You've acked the patch and it was applied in net-next; Obviously it has yet
> to migrate to your tree.

Oh, yeah, that's right.  I knew it sounded familiar, but I didn't
remember where it went.

Looking at its implementation, one obvious difference is that
pcie_get_minimum_link() traverses up the hierarchy and keeps track of
the minimum values it finds.  lspci, on the other hand, just reads
PCI_EXP_LNKSTA from a single device and decodes it.

You said lspci reports x4 for every device from the Root Port all the
way down to your NIC, so I would think the minimum from
pcie_get_minimum_link() would be x4.  But apparently it's not.  Maybe
there's a bug in it.  Can you post the complete "lspci -vv" output
along with your debug patch and output?

Bjorn

^ permalink raw reply

* [PATCH net-next] ipv6: drop fragmented ndisc packets by default (RFC 6980)
From: Hannes Frederic Sowa @ 2013-08-26 23:36 UTC (permalink / raw)
  To: netdev; +Cc: fernando, yoshfuji

This patch implements RFC6980: Drop fragmented ndisc packets by
default. If a fragmented ndisc packet is received the user is informed
that it is possible to disable the check.

Cc: Fernando Gont <fernando@gont.com.ar>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 Documentation/networking/ip-sysctl.txt |  6 ++++++
 include/linux/ipv6.h                   |  1 +
 include/uapi/linux/ipv6.h              |  1 +
 net/ipv6/addrconf.c                    | 10 ++++++++++
 net/ipv6/ndisc.c                       | 17 +++++++++++++++++
 5 files changed, 35 insertions(+)

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index debfe85..a2be556 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1349,6 +1349,12 @@ mldv2_unsolicited_report_interval - INTEGER
 	MLDv2 report retransmit will take place.
 	Default: 1000 (1 second)
 
+suppress_frag_ndisc - INTEGER
+	Control RFC 6980 (Security Implications of IPv6 Fragmentation
+	with IPv6 Neighbor Discovery) behavior:
+	1 - (default) discard fragmented neighbor discovery packets
+	0 - allow fragmented neighbor discovery packets
+
 icmp/*:
 ratelimit - INTEGER
 	Limit the maximal rates for sending ICMPv6 packets.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 9ac5047..28ea384 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -50,6 +50,7 @@ struct ipv6_devconf {
 	__s32		accept_dad;
 	__s32		force_tllao;
 	__s32           ndisc_notify;
+	__s32		suppress_frag_ndisc;
 	void		*sysctl;
 };
 
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index d07ac69..593b0e3 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -162,6 +162,7 @@ enum {
 	DEVCONF_NDISC_NOTIFY,
 	DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
 	DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
+	DEVCONF_SUPPRESS_FRAG_NDISC,
 	DEVCONF_MAX
 };
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2d6d179..a7183fc 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -204,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
 	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
 	.disable_ipv6		= 0,
 	.accept_dad		= 1,
+	.suppress_frag_ndisc	= 1,
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -241,6 +242,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
 	.accept_source_route	= 0,	/* we do not accept RH0 by default. */
 	.disable_ipv6		= 0,
 	.accept_dad		= 1,
+	.suppress_frag_ndisc	= 1,
 };
 
 /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -4188,6 +4190,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
 	array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
 	array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
 	array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
+	array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -5002,6 +5005,13 @@ static struct addrconf_sysctl_table
 			.proc_handler   = proc_dointvec
 		},
 		{
+			.procname	= "suppress_frag_ndisc",
+			.data		= &ipv6_devconf.suppress_frag_ndisc,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec
+		},
+		{
 			/* sentinel */
 		}
 	},
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 04d31c2..41720fe 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1519,10 +1519,27 @@ static void pndisc_redo(struct sk_buff *skb)
 	kfree_skb(skb);
 }
 
+static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
+{
+	struct inet6_dev *idev = __in6_dev_get(skb->dev);
+
+	if (!idev)
+		return true;
+	if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
+	    idev->cnf.suppress_frag_ndisc) {
+		net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
+		return true;
+	}
+	return false;
+}
+
 int ndisc_rcv(struct sk_buff *skb)
 {
 	struct nd_msg *msg;
 
+	if (ndisc_suppress_frag_ndisc(skb))
+		return 0;
+
 	if (skb_linearize(skb))
 		return 0;
 
-- 
1.8.3.1

^ permalink raw reply related

* RE: pcie_get_minimum_link returns 0 width
From: Yuval Mintz @ 2013-08-26 23:36 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: jacob.e.keller@intel.com, linux-pci@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <CAErSpo4NmL0RWcBompuweHNYmhNmLXU_21_gvaqfDEzi+HBp5g@mail.gmail.com>

> > Hi,
> >
> > I tried adding support for the newly added 'pcie_get_minimum_link' into
> the
> > bnx2x driver, but found out the some of my devices started showing width
> x0.
> >
> > By adding debug prints, I've found out there were devices up the chain that
> > Showed 0 when their PCI_EXP_LNKSTA was read by said function.
> > However, when I tried looking via lspci the output claimed the width was
> x4.
> 
> I don't see a 'pcie_get_minimum_link()' function in my current tree
> (git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git "next"
> branch).  Maybe seeing your patch (with the debug prints) would give
> me a hook for somewhere to start looking.

You've acked the patch and it was applied in net-next; Obviously it has yet
to migrate to your tree. 

> 
> Can you figure out why lspci shows the correct value and this kernel
> interface does not?  The current lspci source is in
> git://git.kernel.org/pub/scm/utils/pciutils/pciutils.git and the
> relevant code is probably in cap_express_link() here:
> http://git.kernel.org/cgit/utils/pciutils/pciutils.git/tree/ls-caps.c#n750

Traced the read as going via the pci-sysfs. Where should I look for the bus's
read ops?

Thanks,
Yuval

^ permalink raw reply

* Re: [PATCH net-next 07/16] sfc: Limit scope of a Falcon A1 IRQ workaround
From: Ben Hutchings @ 2013-08-26 22:47 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: David Miller, netdev, linux-net-drivers
In-Reply-To: <521B4AA9.9000906@cogentembedded.com>

On Mon, 2013-08-26 at 16:31 +0400, Sergei Shtylyov wrote:
> Hello.
> 
> On 26-08-2013 3:03, Ben Hutchings wrote:
> 
> > We unconditionally acknowledge legacy interrupts just before disabling
> > them.  This workaround is needed on Falcon A1 but probably not on
> > later chips where the legacy interrupt mechanism is different.  It was
> > also originally done after the IRQ handler was removed, not before.
> > Restore the original behaviour for Falcon A1 only by doing this
> > acknowledgement in the efx_nic_type::fini operation.
> 
> > Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
> > ---
> >   drivers/net/ethernet/sfc/falcon.c |    4 ++--
> >   drivers/net/ethernet/sfc/nic.c    |    7 -------
> >   drivers/net/ethernet/sfc/nic.h    |    1 -
> >   3 files changed, 2 insertions(+), 10 deletions(-)
> 
> > diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
> > index f8de382..4492129 100644
> > --- a/drivers/net/ethernet/sfc/falcon.c
> > +++ b/drivers/net/ethernet/sfc/falcon.c
> > @@ -336,7 +336,7 @@ static void falcon_prepare_flush(struct efx_nic *efx)
> >    *
> >    * NB most hardware supports MSI interrupts
> >    */
> > -inline void falcon_irq_ack_a1(struct efx_nic *efx)
> > +static inline void falcon_irq_ack_a1(struct efx_nic *efx)
> 
>     Does inline make sense still when this now is referenced indirectly?

It's not inlined in the cleanup code, either before or after this
change.  But we do want this to be inlined in the following function,
falcon_legacy_interrupt_a1().  So I think it does make sense.

Ben.

> >   {
> >   	efx_dword_t reg;
> >
> > @@ -2343,7 +2343,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
> >   	.remove = falcon_remove_nic,
> >   	.init = falcon_init_nic,
> >   	.dimension_resources = falcon_dimension_resources,
> > -	.fini = efx_port_dummy_op_void,
> > +	.fini = falcon_irq_ack_a1,
> >   	.monitor = falcon_monitor,
> >   	.map_reset_reason = falcon_map_reset_reason,
> >   	.map_reset_flags = falcon_map_reset_flags,
> 
> WBR, Sergei
> 

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* [PATCH 04/11] net: calxedaxgmac: fix possible skb free before tx complete
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

The TX completion code may have freed an skb before the entire sg list
was transmitted. The DMA unmap calls for the fragments could also get
skipped. Now set the skb pointer on every entry in the ring, not just
the head of the sg list. We then use the FS (first segment) bit in the
descriptors to determine skb head vs. fragment.

This also fixes similar bug in xgmac_free_tx_skbufs where clean-up of
a sg list that wraps at the end of the ring buffer would not get
unmapped.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 55 ++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index df7e3e2..64854ad 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -470,6 +470,11 @@ static inline int desc_get_tx_ls(struct xgmac_dma_desc *p)
 	return le32_to_cpu(p->flags) & TXDESC_LAST_SEG;
 }
 
+static inline int desc_get_tx_fs(struct xgmac_dma_desc *p)
+{
+	return le32_to_cpu(p->flags) & TXDESC_FIRST_SEG;
+}
+
 static inline u32 desc_get_buf_addr(struct xgmac_dma_desc *p)
 {
 	return le32_to_cpu(p->buf1_addr);
@@ -796,7 +801,7 @@ static void xgmac_free_rx_skbufs(struct xgmac_priv *priv)
 
 static void xgmac_free_tx_skbufs(struct xgmac_priv *priv)
 {
-	int i, f;
+	int i;
 	struct xgmac_dma_desc *p;
 
 	if (!priv->tx_skbuff)
@@ -807,16 +812,15 @@ static void xgmac_free_tx_skbufs(struct xgmac_priv *priv)
 			continue;
 
 		p = priv->dma_tx + i;
-		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 desc_get_buf_len(p), DMA_TO_DEVICE);
-
-		for (f = 0; f < skb_shinfo(priv->tx_skbuff[i])->nr_frags; f++) {
-			p = priv->dma_tx + i++;
+		if (desc_get_tx_fs(p))
+			dma_unmap_single(priv->device, desc_get_buf_addr(p),
+					 desc_get_buf_len(p), DMA_TO_DEVICE);
+		else
 			dma_unmap_page(priv->device, desc_get_buf_addr(p),
 				       desc_get_buf_len(p), DMA_TO_DEVICE);
-		}
 
-		dev_kfree_skb_any(priv->tx_skbuff[i]);
+		if (desc_get_tx_ls(p))
+			dev_kfree_skb_any(priv->tx_skbuff[i]);
 		priv->tx_skbuff[i] = NULL;
 	}
 }
@@ -853,8 +857,6 @@ static void xgmac_free_dma_desc_rings(struct xgmac_priv *priv)
  */
 static void xgmac_tx_complete(struct xgmac_priv *priv)
 {
-	int i;
-
 	while (dma_ring_cnt(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ)) {
 		unsigned int entry = priv->tx_tail;
 		struct sk_buff *skb = priv->tx_skbuff[entry];
@@ -864,33 +866,24 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
 		if (desc_get_owner(p))
 			break;
 
-		/* Verify tx error by looking at the last segment */
-		if (desc_get_tx_ls(p))
-			desc_get_tx_status(priv, p);
-
 		netdev_dbg(priv->dev, "tx ring: curr %d, dirty %d\n",
 			priv->tx_head, priv->tx_tail);
 
-		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 desc_get_buf_len(p), DMA_TO_DEVICE);
-
-		priv->tx_skbuff[entry] = NULL;
-		priv->tx_tail = dma_ring_incr(entry, DMA_TX_RING_SZ);
-
-		if (!skb) {
-			continue;
-		}
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			entry = priv->tx_tail = dma_ring_incr(priv->tx_tail,
-							      DMA_TX_RING_SZ);
-			p = priv->dma_tx + priv->tx_tail;
-
+		if (desc_get_tx_fs(p))
+			dma_unmap_single(priv->device, desc_get_buf_addr(p),
+					 desc_get_buf_len(p), DMA_TO_DEVICE);
+		else
 			dma_unmap_page(priv->device, desc_get_buf_addr(p),
 				       desc_get_buf_len(p), DMA_TO_DEVICE);
+
+		/* Check tx error on the last segment */
+		if (desc_get_tx_ls(p)) {
+			desc_get_tx_status(priv, p);
+			dev_kfree_skb(skb);
 		}
 
-		dev_kfree_skb(skb);
+		priv->tx_skbuff[entry] = NULL;
+		priv->tx_tail = dma_ring_incr(entry, DMA_TX_RING_SZ);
 	}
 
 	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
@@ -1110,7 +1103,7 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		entry = dma_ring_incr(entry, DMA_TX_RING_SZ);
 		desc = priv->dma_tx + entry;
-		priv->tx_skbuff[entry] = NULL;
+		priv->tx_skbuff[entry] = skb;
 
 		desc_set_buf_addr_and_size(desc, paddr, len);
 		if (i < (nfrags - 1))
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 11/11] net: calxedaxgmac: fix xgmac_xmit DMA mapping error handling
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

On a DMA mapping error in xgmac_xmit, we should simply free the skb and
return NETDEV_TX_OK rather than -EIO. In the case of errors in mapping
frags, we need to undo everything that has been setup.

Reported-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index f149c08..0022887 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -466,6 +466,13 @@ static inline void desc_set_tx_owner(struct xgmac_dma_desc *p, u32 flags)
 	p->flags = cpu_to_le32(tmpflags);
 }
 
+static inline void desc_clear_tx_owner(struct xgmac_dma_desc *p)
+{
+	u32 tmpflags = le32_to_cpu(p->flags);
+	tmpflags &= TXDESC_END_RING;
+	p->flags = cpu_to_le32(tmpflags);
+}
+
 static inline int desc_get_tx_ls(struct xgmac_dma_desc *p)
 {
 	return le32_to_cpu(p->flags) & TXDESC_LAST_SEG;
@@ -1103,7 +1110,7 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	paddr = dma_map_single(priv->device, skb->data, len, DMA_TO_DEVICE);
 	if (dma_mapping_error(priv->device, paddr)) {
 		dev_kfree_skb(skb);
-		return -EIO;
+		return NETDEV_TX_OK;
 	}
 	priv->tx_skbuff[entry] = skb;
 	desc_set_buf_addr_and_size(desc, paddr, len);
@@ -1115,10 +1122,8 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		paddr = skb_frag_dma_map(priv->device, frag, 0, len,
 					 DMA_TO_DEVICE);
-		if (dma_mapping_error(priv->device, paddr)) {
-			dev_kfree_skb(skb);
-			return -EIO;
-		}
+		if (dma_mapping_error(priv->device, paddr))
+			goto dma_err;
 
 		entry = dma_ring_incr(entry, DMA_TX_RING_SZ);
 		desc = priv->dma_tx + entry;
@@ -1154,6 +1159,22 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 			netif_wake_queue(dev);
 	}
 	return NETDEV_TX_OK;
+
+dma_err:
+	entry = priv->tx_head;
+	for ( ; i > 0; i--) {
+		entry = dma_ring_incr(entry, DMA_TX_RING_SZ);
+		desc = priv->dma_tx + entry;
+		priv->tx_skbuff[entry] = NULL;
+		dma_unmap_page(priv->device, desc_get_buf_addr(desc),
+			       desc_get_buf_len(desc), DMA_TO_DEVICE);
+		desc_clear_tx_owner(desc);
+	}
+	desc = first;
+	dma_unmap_single(priv->device, desc_get_buf_addr(desc),
+			 desc_get_buf_len(desc), DMA_TO_DEVICE);
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
 }
 
 static int xgmac_rx(struct xgmac_priv *priv, int limit)
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 10/11] net: calxedaxgmac: fix rx DMA mapping API size mismatches
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Fix the mismatch in the DMA mapping and unmapping sizes for receive. The
unmap size must be equal to the map size and should not be the actual
received frame length. The map size should also be adjusted by the
NET_IP_ALIGN size since the h/w buffer size (dma_buf_sz) includes this
offset.

Also, add a missing dma_mapping_error check in xgmac_rx_refill.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index b206268..f149c08 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -695,9 +695,14 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
 			if (unlikely(skb == NULL))
 				break;
 
-			priv->rx_skbuff[entry] = skb;
 			paddr = dma_map_single(priv->device, skb->data,
-					       bufsz, DMA_FROM_DEVICE);
+					       priv->dma_buf_sz - NET_IP_ALIGN,
+					       DMA_FROM_DEVICE);
+			if (dma_mapping_error(priv->device, paddr)) {
+				dev_kfree_skb_any(skb);
+				break;
+			}
+			priv->rx_skbuff[entry] = skb;
 			desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
 		}
 
@@ -794,13 +799,14 @@ static void xgmac_free_rx_skbufs(struct xgmac_priv *priv)
 		return;
 
 	for (i = 0; i < DMA_RX_RING_SZ; i++) {
-		if (priv->rx_skbuff[i] == NULL)
+		struct sk_buff *skb = priv->rx_skbuff[i];
+		if (skb == NULL)
 			continue;
 
 		p = priv->dma_rx + i;
 		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 priv->dma_buf_sz, DMA_FROM_DEVICE);
-		dev_kfree_skb_any(priv->rx_skbuff[i]);
+				 priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
+		dev_kfree_skb_any(skb);
 		priv->rx_skbuff[i] = NULL;
 	}
 }
@@ -1190,7 +1196,7 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
 
 		skb_put(skb, frame_len);
 		dma_unmap_single(priv->device, desc_get_buf_addr(p),
-				 frame_len, DMA_FROM_DEVICE);
+				 priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
 
 		skb->protocol = eth_type_trans(skb, priv->dev);
 		skb->ip_summed = ip_checksum;
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 09/11] net: calxedaxgmac: remove some unused statistic counters
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

rx_sa_filter_fail and tx_undeflow events are unused and impossible
to occur based on how the h/w is used. We never filter on source MAC
address and TX store and forward mode prevents underflow events.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 9b6eff5..b206268 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -353,11 +353,9 @@ struct xgmac_extra_stats {
 	/* Receive errors */
 	unsigned long rx_watchdog;
 	unsigned long rx_da_filter_fail;
-	unsigned long rx_sa_filter_fail;
 	unsigned long rx_payload_error;
 	unsigned long rx_ip_header_error;
 	/* Tx/Rx IRQ errors */
-	unsigned long tx_undeflow;
 	unsigned long tx_process_stopped;
 	unsigned long rx_buf_unav;
 	unsigned long rx_process_stopped;
@@ -1584,7 +1582,6 @@ static const struct xgmac_stats xgmac_gstrings_stats[] = {
 	XGMAC_STAT(rx_payload_error),
 	XGMAC_STAT(rx_ip_header_error),
 	XGMAC_STAT(rx_da_filter_fail),
-	XGMAC_STAT(rx_sa_filter_fail),
 	XGMAC_STAT(fatal_bus_error),
 	XGMAC_HW_STAT(rx_watchdog, XGMAC_MMC_RXWATCHDOG),
 	XGMAC_HW_STAT(tx_vlan, XGMAC_MMC_TXVLANFRAME),
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 08/11] net: calxedaxgmac: fix various errors in xgmac_set_rx_mode
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Fix xgmac_set_rx_mode to handle several conditions that were not handled
correctly as Lennert Buytenhek describes:

If we have, say, 100 unicast addresses, and 5 multicast addresses, the
unicast address count check will evaluate to true, and set use_hash to
true.  The multicast address check will however evaluate to false, and
use_hash won't be set to true again, and XGMAC_FRAME_FILTER_HMC won't
be OR'd into XGMAC_FRAME_FILTER, but since use_hash was still true
from the unicast check, netdev_for_each_mc_addr() will program the
multicast addresses into the hash table instead of using the MAC
address registers, but since the HMC bit wasn't set, the hash table
won't be checked for multicast addresses on receive, and we'll stop
receiving multicast packets entirely.

Also, there is no code that zeroes out MAC address registers reg..31
at the end of this function, meaning that under the right conditions,
unicast/multicast addresses that were previously in the filter but
were then deleted won't be cleared out.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 385eca0..9b6eff5 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -618,10 +618,15 @@ static void xgmac_set_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 {
 	u32 data;
 
-	data = (addr[5] << 8) | addr[4] | (num ? XGMAC_ADDR_AE : 0);
-	writel(data, ioaddr + XGMAC_ADDR_HIGH(num));
-	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
-	writel(data, ioaddr + XGMAC_ADDR_LOW(num));
+	if (addr) {
+		data = (addr[5] << 8) | addr[4] | (num ? XGMAC_ADDR_AE : 0);
+		writel(data, ioaddr + XGMAC_ADDR_HIGH(num));
+		data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+		writel(data, ioaddr + XGMAC_ADDR_LOW(num));
+	} else {
+		writel(0, ioaddr + XGMAC_ADDR_HIGH(num));
+		writel(0, ioaddr + XGMAC_ADDR_LOW(num));
+	}
 }
 
 static void xgmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
@@ -1297,6 +1302,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
 	if ((netdev_mc_count(dev) + reg - 1) > XGMAC_MAX_FILTER_ADDR) {
 		use_hash = true;
 		value |= XGMAC_FRAME_FILTER_HMC | XGMAC_FRAME_FILTER_HPF;
+	} else {
+		use_hash = false;
 	}
 	netdev_for_each_mc_addr(ha, dev) {
 		if (use_hash) {
@@ -1313,6 +1320,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
 	}
 
 out:
+	for (i = reg; i < XGMAC_MAX_FILTER_ADDR; i++)
+		xgmac_set_mac_addr(ioaddr, NULL, reg);
 	for (i = 0; i < XGMAC_NUM_HASH; i++)
 		writel(hash_filter[i], ioaddr + XGMAC_HASH(i));
 
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 07/11] net: calxedaxgmac: enable interrupts after napi_enable
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Fix a race condition where the interrupt handler may have called
napi_schedule before napi_enable is called. This would disable interrupts
and never actually schedule napi to run.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index cd5872c..385eca0 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -962,9 +962,7 @@ static int xgmac_hw_init(struct net_device *dev)
 		DMA_BUS_MODE_FB | DMA_BUS_MODE_ATDS | DMA_BUS_MODE_AAL;
 	writel(value, ioaddr + XGMAC_DMA_BUS_MODE);
 
-	/* Enable interrupts */
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
-	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
+	writel(0, ioaddr + XGMAC_DMA_INTR_ENA);
 
 	/* Mask power mgt interrupt */
 	writel(XGMAC_INT_STAT_PMTIM, ioaddr + XGMAC_INT_STAT);
@@ -1032,6 +1030,10 @@ static int xgmac_open(struct net_device *dev)
 	napi_enable(&priv->napi);
 	netif_start_queue(dev);
 
+	/* Enable interrupts */
+	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
+	writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
+
 	return 0;
 }
 
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 06/11] net: calxedaxgmac: fix race with tx queue stop/wake
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Since the xgmac transmit start and completion work locklessly, it is
possible for xgmac_xmit to stop the tx queue after the xgmac_tx_complete
has run resulting in the tx queue never being woken up. Fix this by
ensuring that ring buffer index updates are visible and serialize the
queue wake with netif_tx_lock.

The implementation used here was copied from
drivers/net/ethernet/broadcom/tg3.c.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index f630855..cd5872c 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -410,6 +410,9 @@ struct xgmac_priv {
 #define dma_ring_space(h, t, s)	CIRC_SPACE(h, t, s)
 #define dma_ring_cnt(h, t, s)	CIRC_CNT(h, t, s)
 
+#define tx_dma_ring_space(p) \
+	dma_ring_space((p)->tx_head, (p)->tx_tail, DMA_TX_RING_SZ)
+
 /* XGMAC Descriptor Access Helpers */
 static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
 {
@@ -886,9 +889,14 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
 		priv->tx_tail = dma_ring_incr(entry, DMA_TX_RING_SZ);
 	}
 
-	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
-	    MAX_SKB_FRAGS)
-		netif_wake_queue(priv->dev);
+	/* Ensure tx_tail is visible to xgmac_xmit */
+	smp_mb();
+	if (unlikely(netif_queue_stopped(priv->dev))) {
+		netif_tx_lock(priv->dev);
+		if (tx_dma_ring_space(priv) > MAX_SKB_FRAGS)
+			netif_wake_queue(priv->dev);
+		netif_tx_unlock(priv->dev);
+	}
 }
 
 static void xgmac_tx_timeout_work(struct work_struct *work)
@@ -1125,10 +1133,15 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ);
 
-	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
-	    MAX_SKB_FRAGS)
+	/* Ensure tx_head update is visible to tx completion */
+	smp_mb();
+	if (unlikely(tx_dma_ring_space(priv) < MAX_SKB_FRAGS)) {
 		netif_stop_queue(dev);
-
+		/* Ensure netif_stop_queue is visible to tx completion */
+		smp_mb();
+		if (tx_dma_ring_space(priv) > MAX_SKB_FRAGS)
+			netif_wake_queue(dev);
+	}
 	return NETDEV_TX_OK;
 }
 
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 05/11] net: calxedaxgmac: update ring buffer tx_head after barriers
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

Ensure that the descriptor writes are visible before the ring buffer head
is updated. Since writel is a barrier, we can simply update the head after
the writel.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 64854ad..f630855 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1121,9 +1121,10 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	wmb();
 	desc_set_tx_owner(first, desc_flags | TXDESC_FIRST_SEG);
 
+	writel(1, priv->base + XGMAC_DMA_TX_POLL);
+
 	priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ);
 
-	writel(1, priv->base + XGMAC_DMA_TX_POLL);
 	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
 	    MAX_SKB_FRAGS)
 		netif_stop_queue(dev);
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 03/11] net: calxedaxgmac: fix race between xgmac_tx_complete and xgmac_tx_err
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

It is possible for the xgmac_tx_complete to run concurrently with
xgmac_tx_err since there are no locks. Fix this by moving the tx
error handling to a workqueue so we can disable napi while we reset
the transmitter.

Reported-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 38 +++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index d41af68..df7e3e2 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -393,6 +393,7 @@ struct xgmac_priv {
 	char rx_pause;
 	char tx_pause;
 	int wolopts;
+	struct work_struct tx_timeout_work;
 };
 
 /* XGMAC Configuration Settings */
@@ -897,21 +898,18 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
 		netif_wake_queue(priv->dev);
 }
 
-/**
- * xgmac_tx_err:
- * @priv: pointer to the private device structure
- * Description: it cleans the descriptors and restarts the transmission
- * in case of errors.
- */
-static void xgmac_tx_err(struct xgmac_priv *priv)
+static void xgmac_tx_timeout_work(struct work_struct *work)
 {
-	u32 reg, value, inten;
+	u32 reg, value;
+	struct xgmac_priv *priv =
+		container_of(work, struct xgmac_priv, tx_timeout_work);
 
-	netif_stop_queue(priv->dev);
+	napi_disable(&priv->napi);
 
-	inten = readl(priv->base + XGMAC_DMA_INTR_ENA);
 	writel(0, priv->base + XGMAC_DMA_INTR_ENA);
 
+	netif_tx_lock(priv->dev);
+
 	reg = readl(priv->base + XGMAC_DMA_CONTROL);
 	writel(reg & ~DMA_CONTROL_ST, priv->base + XGMAC_DMA_CONTROL);
 	do {
@@ -927,9 +925,15 @@ static void xgmac_tx_err(struct xgmac_priv *priv)
 
 	writel(DMA_STATUS_TU | DMA_STATUS_TPS | DMA_STATUS_NIS | DMA_STATUS_AIS,
 		priv->base + XGMAC_DMA_STATUS);
-	writel(inten, priv->base + XGMAC_DMA_INTR_ENA);
 
+	netif_tx_unlock(priv->dev);
 	netif_wake_queue(priv->dev);
+
+	napi_enable(&priv->napi);
+
+	/* Enable interrupts */
+	writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_STATUS);
+	writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
 }
 
 static int xgmac_hw_init(struct net_device *dev)
@@ -1225,9 +1229,7 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
 static void xgmac_tx_timeout(struct net_device *dev)
 {
 	struct xgmac_priv *priv = netdev_priv(dev);
-
-	/* Clear Tx resources and restart transmitting again */
-	xgmac_tx_err(priv);
+	schedule_work(&priv->tx_timeout_work);
 }
 
 /**
@@ -1366,7 +1368,6 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
 static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
 {
 	u32 intr_status;
-	bool tx_err = false;
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct xgmac_priv *priv = netdev_priv(dev);
 	struct xgmac_extra_stats *x = &priv->xstats;
@@ -1396,16 +1397,12 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
 		if (intr_status & DMA_STATUS_TPS) {
 			netdev_err(priv->dev, "transmit process stopped\n");
 			x->tx_process_stopped++;
-			tx_err = true;
+			schedule_work(&priv->tx_timeout_work);
 		}
 		if (intr_status & DMA_STATUS_FBI) {
 			netdev_err(priv->dev, "fatal bus error\n");
 			x->fatal_bus_error++;
-			tx_err = true;
 		}
-
-		if (tx_err)
-			xgmac_tx_err(priv);
 	}
 
 	/* TX/RX NORMAL interrupts */
@@ -1708,6 +1705,7 @@ static int xgmac_probe(struct platform_device *pdev)
 	ndev->netdev_ops = &xgmac_netdev_ops;
 	SET_ETHTOOL_OPS(ndev, &xgmac_ethtool_ops);
 	spin_lock_init(&priv->stats_lock);
+	INIT_WORK(&priv->tx_timeout_work, xgmac_tx_timeout_work);
 
 	priv->device = &pdev->dev;
 	priv->dev = ndev;
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 02/11] net: calxedaxgmac: read correct field in xgmac_desc_get_buf_len
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring
In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

xgmac_desc_get_buf_len appears to have a copy/paste error. flags is the
wrong field to read. We should be reading buf_size field. cpu_to_le32
should also be le32_to_cpu. This never really mattered as this function
is only used for DMA mapping calls which happen to be nops with coherent
DMA.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 71f6720..d41af68 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -421,7 +421,7 @@ static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
 
 static inline int desc_get_buf_len(struct xgmac_dma_desc *p)
 {
-	u32 len = cpu_to_le32(p->flags);
+	u32 len = le32_to_cpu(p->buf_size);
 	return (len & DESC_BUFFER1_SZ_MASK) +
 		((len & DESC_BUFFER2_SZ_MASK) >> DESC_BUFFER2_SZ_OFFSET);
 }
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 01/11] net: calxedaxgmac: remove NETIF_F_FRAGLIST setting
From: Rob Herring @ 2013-08-26 22:45 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Andreas Herrmann, Lennert Buytenhek, Rob Herring

From: Rob Herring <rob.herring@calxeda.com>

The xgmac does not actually handle frag lists, so this option should not
be set. It does not appear to have had any impact though.

Reported-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 drivers/net/ethernet/calxeda/xgmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 7cb148c..71f6720 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1759,7 +1759,7 @@ static int xgmac_probe(struct platform_device *pdev)
 	if (device_can_wakeup(priv->device))
 		priv->wolopts = WAKE_MAGIC;	/* Magic Frame as default */
 
-	ndev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA;
+	ndev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA;
 	if (readl(priv->base + XGMAC_DMA_HW_FEATURE) & DMA_HW_FEAT_TXCOESEL)
 		ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 				     NETIF_F_RXCSUM;
-- 
1.8.1.2

^ permalink raw reply related

* Re: [PATCH RFC 0/6] SYNPROXY target v2
From: Pablo Neira Ayuso @ 2013-08-26 22:42 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, netdev, mph, jesper.brouer, as
In-Reply-To: <1377244329-20146-1-git-send-email-kaber@trash.net>

Hi Patrick!

On Fri, Aug 23, 2013 at 09:52:03AM +0200, Patrick McHardy wrote:
> The following patches contain the current version of the SYNPROXY target.

I've been looking at my mailbox and patchwork but I couldn't find the
userspace iptables patches, could you post them?

Thanks!

^ permalink raw reply

* Re: [PATCH v2 net-next] tcp: TSO packets automatic sizing
From: Yuchung Cheng @ 2013-08-26 22:31 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, netdev, Neal Cardwell, Van Jacobson, Tom Herbert
In-Reply-To: <1377548889.8828.130.camel@edumazet-glaptop>

On Mon, Aug 26, 2013 at 1:28 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2013-08-26 at 12:09 -0700, Yuchung Cheng wrote:
>
>> init write of 10MSS now looks good, but the delay still shows up if 9
>> < write-size < 10 MSS...
>>
>> I use packetdrill to do write(14599) bytes of MSS 1460
>>
>> 0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
>> 0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
>> 0.000 bind(3, ..., ...) = 0
>> 0.000 listen(3, 1) = 0
>>
>> 0.100 < S 299245565:299245565(0) win 32792 <mss
>> 1460,sackOK,nop,nop,nop,wscale 7>
>> 0.100 > S. 0:0(0) ack 299245566 <mss 1460,nop,nop,sackOK,nop,wscale 6>
>> 0.200 < . 1:1(0) ack 1 win 257
>> 0.200 accept(3, ..., ...) = 4
>> +.000 write(4, ..., 13141) = 13141
>> +3 %{ print "done" }%
>>
>> and tcpdump shows
>>
>> 31.819958 IP cli > srv: S 299245565:299245565(0) win 32792 <mss 1460,sackOK,nop,
>> nop,nop,wscale 7>
>> 000034 IP srv > cli: S 203810874:203810874(0) ack 299245566 win 29200
>> <mss 1460,nop,nop,sackOK,nop,wscale 6>
>> 099966 IP cli > srv: . ack 1 win 257
>> 000079 IP srv > cli: . 1:2921(2920) ack 1 win 457
>> 000010 IP srv > cli: . 2921:5841(2920) ack 1 win 457
>> 000005 IP srv > cli: . 5841:8761(2920) ack 1 win 457
>> 000004 IP srv > cli: . 8761:11681(2920) ack 1 win 457
>> 199659 IP srv > cli: . 11681:13141(1460) ack 1 win 457
>> ...
>
> It works correctly here, I wonder what's happening on your host.
Sorry! I was testing the wrong patch so ignore my bogus report. I have
to run but will take another look of the new patch later today or
tomorrow.

>
> lpq83:~# tcpdump -p -n -s 0 -i any port 8080 -ttt
> tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
> listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
> 000000 IP 192.0.2.1.42148 > 192.168.0.1.8080: S 299245565:299245565(0) win 32792 <mss 1460,sackOK,nop,nop,nop,wscale 7>
> 000042 IP 192.168.0.1.8080 > 192.0.2.1.42148: S 223873324:223873324(0) ack 299245566 win 29200 <mss 1460,nop,nop,sackOK,nop,wscale 6>
> 099946 IP 192.0.2.1.42148 > 192.168.0.1.8080: . ack 1 win 257
> 000087 IP 192.168.0.1.8080 > 192.0.2.1.42148: . 1:2921(2920) ack 1 win 457
> 000006 IP 192.168.0.1.8080 > 192.0.2.1.42148: . 2921:5841(2920) ack 1 win 457
> 000004 IP 192.168.0.1.8080 > 192.0.2.1.42148: . 5841:8761(2920) ack 1 win 457
> 000004 IP 192.168.0.1.8080 > 192.0.2.1.42148: . 8761:11681(2920) ack 1 win 457
> 000005 IP 192.168.0.1.8080 > 192.0.2.1.42148: . 11681:13141(1460) ack 1 win 457
> 000002 IP 192.168.0.1.8080 > 192.0.2.1.42148: P 13141:13142(1) ack 1 win 457
>
>

^ permalink raw reply

* Re: [PATCH v2 nf-next] netfilter: conntrack: remove the central spinlock
From: Pablo Neira Ayuso @ 2013-08-26 22:28 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: netfilter-devel, netdev, Tom Herbert, Patrick McHardy,
	Jesper Dangaard Brouer
In-Reply-To: <1369244868.3301.343.camel@edumazet-glaptop>

Hi Eric,

Several comments on the expectation side.

On Wed, May 22, 2013 at 10:47:48AM -0700, Eric Dumazet wrote:
[...]
>diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
>index 0283bae..c0823b9 100644
>--- a/net/netfilter/nf_conntrack_core.c
>+++ b/net/netfilter/nf_conntrack_core.c
[...]
> @@ -196,6 +247,47 @@ clean_from_lists(struct nf_conn *ct)
>        nf_ct_remove_expectations(ct);

With this patch, we hold the conntrack lock when calling
clean_from_lists but I think that's not enough.
nf_conntrack_expect_lock spinlock protection is missing here.

> }
[...]
> @@ -820,39 +930,41 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
>  				 ecache ? ecache->expmask : 0,
>  			     GFP_ATOMIC);
>  
> -	spin_lock_bh(&nf_conntrack_lock);
> -	exp = nf_ct_find_expectation(net, zone, tuple);
> -	if (exp) {
> -		pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
> -			 ct, exp);
> -		/* Welcome, Mr. Bond.  We've been expecting you... */
> -		__set_bit(IPS_EXPECTED_BIT, &ct->status);
> -		ct->master = exp->master;
> -		if (exp->helper) {
> -			help = nf_ct_helper_ext_add(ct, exp->helper,
> -						    GFP_ATOMIC);
> -			if (help)
> -				rcu_assign_pointer(help->helper, exp->helper);
> -		}
> +	local_bh_disable();
> +	if (net->ct.expect_count) {
> +		spin_lock(&nf_conntrack_expect_lock);

I also think we have a possible race for expected conntracks. The
problem is that expectations don't bump the refcount of the master
conntrack.

> +		exp = nf_ct_find_expectation(net, zone, tuple);

... Now that we have independent locks for conntrack and expectation
lists, a packet may match an expectation while another CPU is walking
through the nf_ct_delete_from_lists bits using exp->master as input.

> +		if (exp) {
> +			pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
> +				 ct, exp);
> +			/* Welcome, Mr. Bond.  We've been expecting you... */
> +			__set_bit(IPS_EXPECTED_BIT, &ct->status);
> +			ct->master = exp->master;

Then, ct->master points to the (vanished) conntrack.

> +			if (exp->helper) {
> +				help = nf_ct_helper_ext_add(ct, exp->helper,
> +							    GFP_ATOMIC);
> +				if (help)
> +					rcu_assign_pointer(help->helper, exp->helper);
> +			}
>  
>  #ifdef CONFIG_NF_CONNTRACK_MARK
> -		ct->mark = exp->master->mark;
> +			ct->mark = exp->master->mark;
>  #endif
>  #ifdef CONFIG_NF_CONNTRACK_SECMARK
> -		ct->secmark = exp->master->secmark;
> +			ct->secmark = exp->master->secmark;
>  #endif
> -		nf_conntrack_get(&ct->master->ct_general);
> -		NF_CT_STAT_INC(net, expect_new);
> -	} else {
> +			nf_conntrack_get(&ct->master->ct_general);

So this needs to adjust the refcounting logic for expectations, to
bump it earlier, during the expectation insertion.

Regards.

^ permalink raw reply

* Re: pcie_get_minimum_link returns 0 width
From: Bjorn Helgaas @ 2013-08-26 22:05 UTC (permalink / raw)
  To: Yuval Mintz
  Cc: jacob.e.keller@intel.com, linux-pci@vger.kernel.org,
	netdev@vger.kernel.org
In-Reply-To: <979A8436335E3744ADCD3A9F2A2B68A52AD136BE@SJEXCHMB10.corp.ad.broadcom.com>

On Sun, Aug 25, 2013 at 5:21 AM, Yuval Mintz <yuvalmin@broadcom.com> wrote:
> Hi,
>
> I tried adding support for the newly added 'pcie_get_minimum_link' into the
> bnx2x driver, but found out the some of my devices started showing width x0.
>
> By adding debug prints, I've found out there were devices up the chain that
> Showed 0 when their PCI_EXP_LNKSTA was read by said function.
> However, when I tried looking via lspci the output claimed the width was x4.

I don't see a 'pcie_get_minimum_link()' function in my current tree
(git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git "next"
branch).  Maybe seeing your patch (with the debug prints) would give
me a hook for somewhere to start looking.

Can you figure out why lspci shows the correct value and this kernel
interface does not?  The current lspci source is in
git://git.kernel.org/pub/scm/utils/pciutils/pciutils.git and the
relevant code is probably in cap_express_link() here:
http://git.kernel.org/cgit/utils/pciutils/pciutils.git/tree/ls-caps.c#n750

> lspci -vt output:
> [0000:00]-+-00.0  Intel Corporation 5000P Chipset Memory Controller Hub
>              +-02.0-[09-12]--+-00.0-[0a-11]--+-00.0-[0b-0d]--
>                                              +-01.0-[0e-10]--+-00.0  Broadcom
>                                         Corporation NetXtreme II BCM57710
>                                         10-Gigabit PCIe [Everest]
>
> Where:
> 00:02.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x4 Port
> 2 (rev 93)
> 09:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express Upstream
> Port (rev 01)
> 0a:01.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express
> Downstream Port E2 (rev 01)
> 0e:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM57710
> 10-Gigabit PCIe [Everest] (rev 01)
>
> The output for "lspci -vvvv | grep LnkSta for all four is:
> LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt-
> ABWMgmt-
>
> But added prints inside the function's loop show:
> LnkSta 1041 [000e:00.00]
> LnkSta 0000 [000a:01.00]
> LnkSta 0000 [0009:00.00]
> LnkSta 3041 [0000:02.00]
> (PCI_EXP_LNKSTA value, bus->number, PCI_SLOT, PCI_FUNC)
>
> Thanks,
> Yuval
>

^ permalink raw reply

* Re: [PATCH 2/2] sh_eth: remove 'register_type' field from 'struct sh_eth_plat_data'
From: Sergei Shtylyov @ 2013-08-26 21:30 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: netdev, davem, lethal, linux-sh
In-Reply-To: <2054715.7J5PzTuKLW@avalon>

Hello.

On 08/21/2013 04:58 PM, Laurent Pinchart wrote:

    Sorry for the belated reply.

>>>>>>>>> Now that the 'register_type' field of the 'sh_eth' driver's platform
>>>>>>>>> data is not used by the driver anymore, it's time to remove it and
>>>>>>>>> its initializers from the SH platform code. Also  move *enum*
>>>>>>>>> declaring values for this  field from <linux/sh_eth.h>  to  the
>>>>>>>>> local driver's header file as they're only needed by the driver
>>>>>>>>> itself now...

>>>>>>>>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

>>>>>> [...]

>>>>>>>>>      /* Driver's parameters */
>>>>>>>>>      #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
>>>>>>>>>      #define SH4_SKB_RX_ALIGN    32
>>>>>>>>>
>>>>>>>>> Index: net-next/include/linux/sh_eth.h
>>>>>>>>> ===================================================================
>>>>>>>>> --- net-next.orig/include/linux/sh_eth.h
>>>>>>>>> +++ net-next/include/linux/sh_eth.h
>>>>>>>>> @@ -5,17 +5,10 @@
>>>>>>>>>
>>>>>>>>>      #include <linux/if_ether.h>
>>>>>>>>>
>>>>>>>>>      enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
>>>>>>>>>
>>>>>>>>> -enum {
>>>>>>>>> -    SH_ETH_REG_GIGABIT,
>>>>>>>>> -    SH_ETH_REG_FAST_RCAR,
>>>>>>>>> -    SH_ETH_REG_FAST_SH4,
>>>>>>>>> -    SH_ETH_REG_FAST_SH3_SH2
>>>>>>>>> -};
>>>>>>>>>
>>>>>>>>>      struct sh_eth_plat_data {
>>>>>>>>>
>>>>>>>>>          int phy;
>>>>>>>>>          int edmac_endian;

>>>>>>>> Wouldn't it make sense to move the edmac_endian field to
>>>>>>>> sh_eth_cpu_data as well ?

>>>>>>> No, it depends on the SoC endianness which is determined by power-on
>>>>>>> pin strapping -- which is board specific.

>>>>> Does SoC endianness affect the ARM core endianness, the ethernet
>>>>> registers endianness, or both ?

>>>> Both, AFAIK.

>>>>> If it affects the ARM core endianness only, the kernel needs to be
>>>>> compiled in little-endian or big-endian mode anyway, and the sh_eth
>>>>> driver should use cpu_to_le32() unconditionally. If it affects both the
>>>>> ARM core and the ethernet controller there's not need to care about the
>>>>> endianness, as it will always be good.

>>>> No, it won't unless you're using __raw_{readl|writel}() accessors. The
>>>> driver doesn't do it. {readl|writel}() and io{read|write}32() that use
>>>> them always assume LE ordering of memory.

>>>>> We only need to care about it if it affects the ethernet controller
>>>>> registers only, which would seem weird to me.

>>>> Unfortunately, you are wrong.

>>> Care to explain *why* ? There might be bugs in the driver (such as using
>>> the wrong I/O accessors), but I don't see why we need to configure the
>>> endianness through platform data.

>> Re-read my reply about the power-on pin strapping please. The SoC endianness
>> setting gets read from the external source to the SoC, i.e. it's determined
>> by the board.

> Unless that pin doesn't affect the CPU core (in which case I wonder what it's
> used for),

    The thing is I don't have the necessary information about SH SoCs for 
which the 'edmac_endian' field was first added. I'm basing my assumptions on 
the R-Car manuals which claim that both register and DMA descriptor endianness 
depend on the SoC endianness (which is selected by the MD8 pin at power-on). 
So I don't even understand why it's called 'edmac_endian' based on this info, 
as it apparently determines only DMA descriptor endianness.

> the kernel will need to be compiled for the specified endianness
> anyway. Endianness conversion can thus be performed with cpu_to_* (if the
> registers endianness is fixed) or skipped completely (if the registers
> endianness is also configured by the bootstrap pin) by using raw I/O
> accessors.

    Unfortunately, the raw accessors also miss the barriers which might be 
necessary.

> Modifications will be need in the sh_eth driver, but I don't see
> why the driver would need to receive endianness information from platform data
> or DT.

    So you suggest that we use __LITTLE_ENDIAN/__BIG_ENDIAN pre-defined macros 
as when we're programing the EDMR.EL bit to enable automatic data swapping 
feature (it doesn't swap register or descriptors, only the raw data)?

WBR, Sergei

^ permalink raw reply

* Re: [PATCH RESEND V3 net-next 2/3] net: huawei_cdc_ncm: Introduce the huawei_cdc_ncm driver
From: Joe Perches @ 2013-08-26 21:25 UTC (permalink / raw)
  To: David Miller; +Cc: mrkiko.rs, gregkh, oliver, linux-kernel, linux-usb, netdev
In-Reply-To: <20130826.170922.2228024390320689580.davem@davemloft.net>

On Mon, 2013-08-26 at 17:09 -0400, David Miller wrote:
> From: Joe Perches <joe@perches.com>
[]
> Don't try to over-simplify things and act as if they are black
> and white when they aren't.

It wasn't me simplifying.

I commented on your request to:

"order local function variable declarations by line
 length, longest to shortest."

as it seemed a bit rigid.

And perhaps you didn't read the rest of my email.

>> As a general rule, it's I suppose OK, but as
>> a hardened rule, it's like most all hard rules.
>> It's made to be broken.

^ permalink raw reply

* Re: travelling...
From: David Miller @ 2013-08-26 21:10 UTC (permalink / raw)
  To: ordex; +Cc: netdev, linux-wireless, netfilter-devel
In-Reply-To: <20130823201648.GC2896@ritirata.org>

From: Antonio Quartulli <ordex@autistici.org>
Date: Fri, 23 Aug 2013 22:16:48 +0200

> On Fri, Aug 23, 2013 at 08:29:43PM +0200, Hannes Frederic Sowa wrote:
>> On Fri, Aug 23, 2013 at 11:13:08AM -0700, David Miller wrote:
>> > 
>> > I'm travelling over the weekend so I won't be as responsive as
>> > usual.
>> > 
>> > I just pushed 'net' to Linus and he pulled it in.  I plan to work
>> > on my next set of -stable submissions this coming Monday.
>> > 
>> > If a merge of 'net' into 'net-next' would be useful for someone,
>> > now would be a really good time to tell me.
>> 
>> If it would not take you too much time, it would be nice. I depend on
>> a change in net to make another small patch. :)
> 
> If possible I'd need that too in order to send a couple of changes to net-next.

Ok, that's two requests so I did merge net into net-next just now.

^ 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