Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] cfg80211: deprecate CFG80211_WEXT
From: C. McPherson @ 2012-05-18 17:39 UTC (permalink / raw)
  To: netdev, Christopher Worsley, Adam
In-Reply-To: <20120516214048.739945597@sipsolutions.net>

Please reconsider this! We still have applications that still use some 
CFG80211_WEXT functions. Can't you just disable it as default?

-Clyde

On 05/16/2012 05:40 PM, Johannes Berg wrote:

^ permalink raw reply

* Re: [PATCH net-next v5] be2net: Fix to allow get/set of debug levels in the firmware.
From: David Miller @ 2012-05-18 17:33 UTC (permalink / raw)
  To: bhutchings; +Cc: somnath.kotur, netdev, suresh.reddy
In-Reply-To: <1337354667.2696.3.camel@bwh-desktop.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Fri, 18 May 2012 16:24:27 +0100

> On Fri, 2012-05-18 at 14:29 +0530, Somnath Kotur wrote:
>> Patch re-spin.
>> Incorporated review comments by Ben Hutchings.
>> 
>> Signed-off-by: Suresh Reddy <suresh.reddy@emulex.com>
>> Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
> 
> Acked-by: Ben Hutchings <bhutchings@solarflare.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH 00/10] Doorbell drop recovery for Chelsio T4 iWARP
From: David Miller @ 2012-05-18 17:32 UTC (permalink / raw)
  To: vipul-ut6Up61K2wZBDgjK7y7TUQ
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	roland-BHEL68pLQRGGvPXPguhicg, divy-ut6Up61K2wZBDgjK7y7TUQ,
	dm-ut6Up61K2wZBDgjK7y7TUQ, kumaras-ut6Up61K2wZBDgjK7y7TUQ,
	swise-7bPotxP6k4+P2YhJcF5u+vpXobYPEAuW
In-Reply-To: <1337335173-3226-1-git-send-email-vipul-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Vipul Pandya <vipul-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Date: Fri, 18 May 2012 15:29:23 +0530

> Below is a link where Roland advised to re-post the series.
> http://www.spinics.net/lists/netdev/msg187997.html

Roland, who takes this, you or me?
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net-next] ipv6: remove csummode in ip6_append_data()
From: David Miller @ 2012-05-18 17:31 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1337355476.7029.46.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 18 May 2012 17:37:56 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> csummode variable is always CHECKSUM_NONE in ip6_append_data()
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] net: introduce netdev_alloc_frag()
From: David Miller @ 2012-05-18 17:31 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1337353932.7029.34.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 18 May 2012 17:12:12 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> Fix two issues introduced in commit a1c7fff7e18f5
> ( net: netdev_alloc_skb() use build_skb() )
> 
> - Must be IRQ safe (non NAPI drivers can use it)
> - Must not leak the frag if build_skb() fails to allocate sk_buff
> 
> This patch introduces netdev_alloc_frag() for drivers willing to
> use build_skb() instead of __netdev_alloc_skb() variants.
> 
> Factorize code so that :
> __dev_alloc_skb() is a wrapper around __netdev_alloc_skb(), and
> dev_alloc_skb() a wrapper around netdev_alloc_skb()
> 
> Use __GFP_COLD flag.
> 
> Almost all network drivers now benefit from skb->head_frag
> infrastructure.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] iwlwifi: dont pull too much payload in skb head
From: David Miller @ 2012-05-18 17:31 UTC (permalink / raw)
  To: johannes.berg; +Cc: eric.dumazet, netdev, wey-yi.w.guy
In-Reply-To: <1DC40B07CD6EC041A66726C271A73AE61955AE5D@IRSMSX102.ger.corp.intel.com>

From: "Berg, Johannes" <johannes.berg@intel.com>
Date: Fri, 18 May 2012 14:59:04 +0000

>> Since merge window is now pretty close, I would prefer David applies this
>> directly in net-next, if you dont mind, as this patch is more a core network issue
>> than an iwlwifi one.
>> 
>> Thanks !
> 
> Sure, good with me, I don't think we have colliding patches.
> 
> Reviewed-by: Johannes Berg <johannes.berg@intel.com>

Applied.

^ permalink raw reply

* RE: [NET_NEXT RFC PATCH 1/3] ixgbe: add debugfs support
From: Sullivan, Catherine @ 2012-05-18 17:10 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev@vger.kernel.org
In-Reply-To: <20120509161029.4a8f644b@nehalam.linuxnetplumber.net>

> From: Stephen Hemminger [mailto:shemminger@vyatta.com]
> Sent: Wednesday, May 09, 2012 4:10 PM
> 
> On Wed, 09 May 2012 16:09:40 -0700
> Catherine Sullivan <catherine.sullivan@intel.com> wrote:
> 
> > This patch adds debugfs support to the ixgbe driver to give users the
> > ability to access kernel information and to simulate kernel events.
> >
> > The filesystem is set up in the following driver/PCI-instance
> > hierarchy:
> > <debugfs>
> >    |-- ixgbe
> > 	|-- PCI instance
> > 	|	|-- attribute files
> > 	|-- PCI instance
> > 		|-- attribute files
> >
> > Signed-off-by: Catherine Sullivan <catherine.sullivan@intel.com>
> 
> This should be an optional configuration since it is meant for special
> case usage. See SKY2_DEBUG

After looking through the kernel, there doesn't seem to be a clear precedence for this. As was pointed out, SKY2_DEBUG is an optional configuration on its own. However regmap uses debugfs, and it is only optional based on CONFIG_DEBUG_FS, which is how this patch is currently set up. This patch does not have much overhead and we would prefer that it be enabled with CONFIG_DEBUG_FS. 

^ permalink raw reply

* Re: [RFC:kvm] export host NUMA info to guest & make emulated device NUMA attr
From: Shirley Ma @ 2012-05-18 16:14 UTC (permalink / raw)
  To: Liu Ping Fan
  Cc: kvm, netdev, linux-kernel, qemu-devel, Avi Kivity,
	Michael S. Tsirkin, Srivatsa Vaddagiri, Rusty Russell,
	Anthony Liguori, Ryan Harper, Shirley Ma, Krishna Kumar,
	Tom Lendacky
In-Reply-To: <1337246456-30909-1-git-send-email-kernelfans@gmail.com>

On Thu, 2012-05-17 at 17:20 +0800, Liu Ping Fan wrote:
> Currently, the guest can not know the NUMA info of the vcpu, which
> will
> result in performance drawback.
> 
> This is the discovered and experiment by
>         Shirley Ma <xma@us.ibm.com>
>         Krishna Kumar <krkumar2@in.ibm.com>
>         Tom Lendacky <toml@us.ibm.com>
> Refer to -
> http://www.mail-archive.com/kvm@vger.kernel.org/msg69868.html
> we can see the big perfermance gap between NUMA aware and unaware.
> 
> Enlightened by their discovery, I think, we can do more work -- that
> is to
> export NUMA info of host to guest.

There three problems we've found:

1. KVM doesn't support NUMA load balancer. Even there are no other
workloads in the system, and the number of vcpus on the guest is smaller
than the number of cpus per node, the vcpus could be scheduled on
different nodes. 

Someone is working on in-kernel solution. Andrew Theurer has a working
user-space NUMA aware VM balancer, it requires libvirt and cgroups
(which is default for RHEL6 systems).

2. The host scheduler is not aware the relationship between guest vCPUs
and vhost. So it's possible for host scheduler to schedule per-device
vhost thread on the same cpu on which the vCPU kick a TX packet, or
schecule vhost thread on different node than the vCPU for; For RX packet
it's possible for vhost delivers RX packet on the vCPU running on
different node too.

3. per-device vhost thread is not scaled.

So the problems are in host scheduling and vhost thread scalability. I
am not sure how much help from exposing NUMA info from host to guest.

Have you tested these patched? How much performance gain here?

Thanks
Shirley 

> So here comes the idea:
> 1. export host numa info through guest's sched domain to its scheduler
>   Export vcpu's NUMA info to guest scheduler(I think mem NUMA problem
>   has been handled by host).  So the guest's lb will consider the
> cost.
>   I am still working on this, and my original idea is to export these
> info
>   through "static struct sched_domain_topology_level
> *sched_domain_topology"
>   to guest.
> 
> 2. Do a better emulation of virt mach exported to guest.
>   In real world, the devices are limited by kinds of reasons to own
> the NUMA
>   property. But as to Qemu, the device is emulated by thread, which
> inherit
>   the NUMA attr in nature.  We can implement the device as components
> of many
>   logic units, each of the unit is backed by a thread in different
> host node.
>   Currently, I want to start the work on vhost. But I think, maybe in
>   future, the iothread in Qemu can also has such attr.
> 
> 
> Forgive me, for the limited time, I can not have more better
> understand of
> vhost/virtio_net drivers. These patches are just draft, _FAR_, _FAR_
> from work.
> I will do more detail work for them in future.
> 
> To easy the review, the following is the sum up of the 2nd point of
> the idea.
> As for the 1st point of the idea, it is not reflected in the patches.
> 
> --spread/shrink the vhost_workers over the host nodes as demanded from
> Qemu.
>   And we can consider each vhost_worker as an independent net logic
> device
>   embeded in physical device "vhost_net".  At the meanwhile, we spread
> vcpu
>   threads over the host node. 
>   The vrings on guest are allocated PAGE_SIZE align separately, so
> they can 
>   will only be mapped into different host node, so vhost_worker in the
> same
>   node can access it with the least cost. So does the vq on guest.
> 
> --virtio_net driver will changes and talk with the logic device. And
> which
>   logic device it will talk to is determined by on which vcpu it is
> scheduled.
> 
> --the binding of vcpus and vhost_worker is implemented by: 
>   for call direction, vq-a in the node-A will have a dedicated irq-a.
> And 
>   we set the irq-a's affinity to vcpus in node-A.
>   for kick direction, kick register-b trigger different eventfd-b
> which wake up
>   vhost_worker-b.
> 
> 
> 


^ permalink raw reply

* Re: TCPBacklogDrops during aggressive bursts of traffic
From: Kieran Mansley @ 2012-05-18 15:53 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Ben Hutchings, netdev
In-Reply-To: <1337356176.7029.47.camel@edumazet-glaptop>

On Fri, 2012-05-18 at 17:49 +0200, Eric Dumazet wrote:
> 
> Are you playing with SO_RCVBUF, or let the stack autotune it ? 

Just letting the stack autotune it.

Kieran

^ permalink raw reply

* Re: TCPBacklogDrops during aggressive bursts of traffic
From: Eric Dumazet @ 2012-05-18 15:49 UTC (permalink / raw)
  To: Kieran Mansley; +Cc: Ben Hutchings, netdev
In-Reply-To: <1337355955.15044.24.camel@kjm-desktop.uk.level5networks.com>

On Fri, 2012-05-18 at 16:45 +0100, Kieran Mansley wrote:
> On Thu, 2012-05-17 at 18:37 +0200, Eric Dumazet wrote:
> > 
> > Hmm, I was not suggesting running production servers with this
> > setting, only do an experiment.
> 
> OK.  I've found a more reliable way to reproduce it (use MSG_WAITALL to
> make the recv call wait till the socket buffer will be more full) and
> tried with the tcp_adv_win_scale to -2.  It's hard to make any confident
> assertions about the impact of it, but if it does change the behaviour
> it is a small change.  There are certainly still plenty of drops with
> that setting.

Are you playing with SO_RCVBUF, or let the stack autotune it ?

^ permalink raw reply

* Re: TCPBacklogDrops during aggressive bursts of traffic
From: Kieran Mansley @ 2012-05-18 15:45 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Ben Hutchings, netdev
In-Reply-To: <1337272654.3403.20.camel@edumazet-glaptop>

On Thu, 2012-05-17 at 18:37 +0200, Eric Dumazet wrote:
> 
> Hmm, I was not suggesting running production servers with this
> setting, only do an experiment.

OK.  I've found a more reliable way to reproduce it (use MSG_WAITALL to
make the recv call wait till the socket buffer will be more full) and
tried with the tcp_adv_win_scale to -2.  It's hard to make any confident
assertions about the impact of it, but if it does change the behaviour
it is a small change.  There are certainly still plenty of drops with
that setting.

> With net-next and tcp coalescing, I no longer have TCPBacklogDrops /
> collapses, but I dont have sfc card/driver. 

I'll try that.

Kieran

^ permalink raw reply

* [PATCH net-next] ipv6: remove csummode in ip6_append_data()
From: Eric Dumazet @ 2012-05-18 15:37 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

From: Eric Dumazet <edumazet@google.com>

csummode variable is always CHECKSUM_NONE in ip6_append_data()

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv6/ip6_output.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index be2264e..a254e4b 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1198,7 +1198,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	int copy;
 	int err;
 	int offset = 0;
-	int csummode = CHECKSUM_NONE;
 	__u8 tx_flags = 0;
 
 	if (flags&MSG_PROBE)
@@ -1411,7 +1410,7 @@ alloc_new_skb:
 			/*
 			 *	Fill in the control structures
 			 */
-			skb->ip_summed = csummode;
+			skb->ip_summed = CHECKSUM_NONE;
 			skb->csum = 0;
 			/* reserve for fragmentation and ipsec header */
 			skb_reserve(skb, hh_len + sizeof(struct frag_hdr) +
@@ -1454,7 +1453,6 @@ alloc_new_skb:
 			transhdrlen = 0;
 			exthdrlen = 0;
 			dst_exthdrlen = 0;
-			csummode = CHECKSUM_NONE;
 
 			/*
 			 * Put the packet on the pending queue

^ permalink raw reply related

* Re: [V2 PATCH 9/9] vhost: zerocopy: poll vq in zerocopy callback
From: Shirley Ma @ 2012-05-18 15:29 UTC (permalink / raw)
  To: Jason Wang
  Cc: Michael S. Tsirkin, eric.dumazet, netdev, linux-kernel, ebiederm,
	davem
In-Reply-To: <4FB61D57.4030103@redhat.com>

On Fri, 2012-05-18 at 17:58 +0800, Jason Wang wrote:
> On 05/17/2012 11:34 PM, Shirley Ma wrote:
> > On Thu, 2012-05-17 at 10:50 +0800, Jason Wang wrote:
> >> The problem is we may stop the tx queue when there no enough
> capacity
> >> to
> >> place packets, at this moment  we depends on the tx interrupt to
> >> re-enable the tx queue. So if we didn't poll the vhost during
> >> callback,
> >> guest may lose the tx interrupt to re-enable the tx queue which
> could
> >> stall the whole tx queue.
> > VHOST_MAX_PEND should handle the capacity.
> >
> > Hasn't the above situation been handled in handle_tx() code?:
> > ...
> >                          if (unlikely(num_pends>  VHOST_MAX_PEND)) {
> >                                  tx_poll_start(net, sock);
> >
> set_bit(SOCK_ASYNC_NOSPACE,&sock->flags);
> >                                  break;
> >                          }
> > ...
> >
> > Thanks
> > Shirley
> 
> It may not help in because:
> 
> - tx polling depends on skb_orphan() which is often called by device 
> driver when it place the packet into the queue of the devices instead 
> of  when the packets were sent. So it was too early for vhost to be 
> notified.
Then do you think it's better to replace with vhost_poll_queue here
instead?

> - it only works when the pending DMAs exceeds VHOST_MAX_PEND, it's 
> highly possible that guest needs to be notified when the pending
> packets 
> isn't so much.
In which situation the guest needs to be notified when there is no TX
besides buffers run out?

> So this piece of code may not help and could be removed and we need
> to 
> poll the virt-queue during zerocopy callback ( through it could be 
> further optimized but may not be easy). 

Thanks
Shirley

^ permalink raw reply

* Re: [PATCH net-next v5] be2net: Fix to allow get/set of debug levels in the firmware.
From: Ben Hutchings @ 2012-05-18 15:24 UTC (permalink / raw)
  To: Somnath Kotur; +Cc: netdev, Suresh Reddy
In-Reply-To: <66e444e7-aef9-4ce5-a695-10a70fe3b31e@exht1.ad.emulex.com>

On Fri, 2012-05-18 at 14:29 +0530, Somnath Kotur wrote:
> Patch re-spin.
> Incorporated review comments by Ben Hutchings.
> 
> Signed-off-by: Suresh Reddy <suresh.reddy@emulex.com>
> Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>

Acked-by: Ben Hutchings <bhutchings@solarflare.com>

-- 
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

* Re: [V2 PATCH 2/9] macvtap: zerocopy: fix truesize underestimation
From: Shirley Ma @ 2012-05-18 15:22 UTC (permalink / raw)
  To: Jason Wang; +Cc: eric.dumazet, mst, netdev, linux-kernel, ebiederm, davem
In-Reply-To: <4FB62009.2050900@redhat.com>

On Fri, 2012-05-18 at 18:10 +0800, Jason Wang wrote:
> > On Thu, 2012-05-17 at 10:59 +0800, Jason Wang wrote:
> >> Didn't see how this affact skb->len. And for truesize, I think they
> >> are
> >> different, when the offset were not zero, the data in this vector
> >> were
> >> divided into two parts. First part is copied into skb directly, and
> >> the
> >> second were pinned from a whole userspace page by
> >> get_user_pages_fast(),
> >> so we need count the whole page to the socket limit to prevent evil
> >> application.
> > What I meant that the code for skb->truesize has double added the
> first
> > offset if any left from that vector (partically copied into skb
> > directly, and then count pagesize which includes the offset
> (truesize +=
> > PAGE_SIZE)).
> 
> Yes, I get you mean. There's no difference between first frag and 
> others: it's also possible for other frags that didn't occupy the
> whole 
> page. Since we pin the whole user page, better to count the whole
> page 
> size to prevent evil application. 

The difference between first frags and others is other frags might not
occupy the whole page, but the first frags extra offset was doubled
added in skb truesize.

So it's ok for skb->truesize to be bigger than all the skb pinned pages
here?

Thanks
Shirley

^ permalink raw reply

* RE: [PATCH net-next] iwlwifi: dont pull too much payload in skb head
From: Eric Dumazet @ 2012-05-18 15:21 UTC (permalink / raw)
  To: Berg, Johannes; +Cc: David Miller, netdev, Guy, Wey-Yi W
In-Reply-To: <1DC40B07CD6EC041A66726C271A73AE61955AE5D@IRSMSX102.ger.corp.intel.com>

On Fri, 2012-05-18 at 14:59 +0000, Berg, Johannes wrote:
> > Since merge window is now pretty close, I would prefer David applies this
> > directly in net-next, if you dont mind, as this patch is more a core network issue
> > than an iwlwifi one.
> > 
> > Thanks !
> 
> Sure, good with me, I don't think we have colliding patches.
> 
> Reviewed-by: Johannes Berg <johannes.berg@intel.com>

Thanks

> We may want to move this code into mac80211 later though since it also
> has an if (pull in everything, even reallocating if necessary, if it's
> a management frame), but that can wait, I think we're the only driver
> using paged RX.

This is OK, these frames wont be injected in linux IP/TCP stack.

Or maybe you would like an optimized version of skb_header_pointer(),
avoiding the copy if the whole blob can be part of _one_ fragment ?

^ permalink raw reply

* [PATCH net-next] net: introduce netdev_alloc_frag()
From: Eric Dumazet @ 2012-05-18 15:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

From: Eric Dumazet <edumazet@google.com>

Fix two issues introduced in commit a1c7fff7e18f5
( net: netdev_alloc_skb() use build_skb() )

- Must be IRQ safe (non NAPI drivers can use it)
- Must not leak the frag if build_skb() fails to allocate sk_buff

This patch introduces netdev_alloc_frag() for drivers willing to
use build_skb() instead of __netdev_alloc_skb() variants.

Factorize code so that :
__dev_alloc_skb() is a wrapper around __netdev_alloc_skb(), and
dev_alloc_skb() a wrapper around netdev_alloc_skb()

Use __GFP_COLD flag.

Almost all network drivers now benefit from skb->head_frag
infrastructure.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/linux/skbuff.h |   42 ++++++++-----------
 net/core/skbuff.c      |   82 +++++++++++++++++++--------------------
 2 files changed, 59 insertions(+), 65 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index bb47314..fe37c21 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1680,31 +1680,11 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
 		kfree_skb(skb);
 }
 
-/**
- *	__dev_alloc_skb - allocate an skbuff for receiving
- *	@length: length to allocate
- *	@gfp_mask: get_free_pages mask, passed to alloc_skb
- *
- *	Allocate a new &sk_buff and assign it a usage count of one. The
- *	buffer has unspecified headroom built in. Users should allocate
- *	the headroom they think they need without accounting for the
- *	built in space. The built in space is used for optimisations.
- *
- *	%NULL is returned if there is no free memory.
- */
-static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
-					      gfp_t gfp_mask)
-{
-	struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
-	if (likely(skb))
-		skb_reserve(skb, NET_SKB_PAD);
-	return skb;
-}
-
-extern struct sk_buff *dev_alloc_skb(unsigned int length);
+extern void *netdev_alloc_frag(unsigned int fragsz);
 
 extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
-		unsigned int length, gfp_t gfp_mask);
+					  unsigned int length,
+					  gfp_t gfp_mask);
 
 /**
  *	netdev_alloc_skb - allocate an skbuff for rx on a specific device
@@ -1720,11 +1700,25 @@ extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
  *	allocates memory it can be called from an interrupt.
  */
 static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
-		unsigned int length)
+					       unsigned int length)
 {
 	return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
 }
 
+/* legacy helper around __netdev_alloc_skb() */
+static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+					      gfp_t gfp_mask)
+{
+	return __netdev_alloc_skb(NULL, length, gfp_mask);
+}
+
+/* legacy helper around netdev_alloc_skb() */
+static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+	return netdev_alloc_skb(NULL, length);
+}
+
+
 static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
 		unsigned int length, gfp_t gfp)
 {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7645df1..f0bcbe6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -300,6 +300,40 @@ struct netdev_alloc_cache {
 static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
 
 /**
+ * netdev_alloc_frag - allocate a page fragment
+ * @fragsz: fragment size
+ *
+ * Allocates a frag from a page for receive buffer.
+ * Uses GFP_ATOMIC allocations.
+ */
+void *netdev_alloc_frag(unsigned int fragsz)
+{
+	struct netdev_alloc_cache *nc;
+	void *data = NULL;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	nc = &__get_cpu_var(netdev_alloc_cache);
+	if (unlikely(!nc->page)) {
+refill:
+		nc->page = alloc_page(GFP_ATOMIC | __GFP_COLD);
+		nc->offset = 0;
+	}
+	if (likely(nc->page)) {
+		if (nc->offset + fragsz > PAGE_SIZE) {
+			put_page(nc->page);
+			goto refill;
+		}
+		data = page_address(nc->page) + nc->offset;
+		nc->offset += fragsz;
+		get_page(nc->page);
+	}
+	local_irq_restore(flags);
+	return data;
+}
+EXPORT_SYMBOL(netdev_alloc_frag);
+
+/**
  *	__netdev_alloc_skb - allocate an skbuff for rx on a specific device
  *	@dev: network device to receive on
  *	@length: length to allocate
@@ -313,32 +347,20 @@ static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
  *	%NULL is returned if there is no free memory.
  */
 struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
-		unsigned int length, gfp_t gfp_mask)
+				   unsigned int length, gfp_t gfp_mask)
 {
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +
 			      SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
 	if (fragsz <= PAGE_SIZE && !(gfp_mask & __GFP_WAIT)) {
-		struct netdev_alloc_cache *nc;
-		void *data = NULL;
+		void *data = netdev_alloc_frag(fragsz);
 
-		nc = &get_cpu_var(netdev_alloc_cache);
-		if (!nc->page) {
-refill:			nc->page = alloc_page(gfp_mask);
-			nc->offset = 0;
-		}
-		if (likely(nc->page)) {
-			if (nc->offset + fragsz > PAGE_SIZE) {
-				put_page(nc->page);
-				goto refill;
-			}
-			data = page_address(nc->page) + nc->offset;
-			nc->offset += fragsz;
-			get_page(nc->page);
+		if (likely(data)) {
+			skb = build_skb(data, fragsz);
+			if (unlikely(!skb))
+				put_page(virt_to_head_page(data));
 		}
-		put_cpu_var(netdev_alloc_cache);
-		skb = data ? build_skb(data, fragsz) : NULL;
 	} else {
 		skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE);
 	}
@@ -360,28 +382,6 @@ void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
 }
 EXPORT_SYMBOL(skb_add_rx_frag);
 
-/**
- *	dev_alloc_skb - allocate an skbuff for receiving
- *	@length: length to allocate
- *
- *	Allocate a new &sk_buff and assign it a usage count of one. The
- *	buffer has unspecified headroom built in. Users should allocate
- *	the headroom they think they need without accounting for the
- *	built in space. The built in space is used for optimisations.
- *
- *	%NULL is returned if there is no free memory. Although this function
- *	allocates memory it can be called from an interrupt.
- */
-struct sk_buff *dev_alloc_skb(unsigned int length)
-{
-	/*
-	 * There is more code here than it seems:
-	 * __dev_alloc_skb is an inline
-	 */
-	return __dev_alloc_skb(length, GFP_ATOMIC);
-}
-EXPORT_SYMBOL(dev_alloc_skb);
-
 static void skb_drop_list(struct sk_buff **listp)
 {
 	struct sk_buff *list = *listp;

^ permalink raw reply related

* RE: [PATCH net-next] iwlwifi: dont pull too much payload in skb head
From: Berg, Johannes @ 2012-05-18 14:59 UTC (permalink / raw)
  To: Eric Dumazet, David Miller; +Cc: netdev, Guy, Wey-Yi W
In-Reply-To: <1337352513.7029.18.camel@edumazet-glaptop>

> Since merge window is now pretty close, I would prefer David applies this
> directly in net-next, if you dont mind, as this patch is more a core network issue
> than an iwlwifi one.
> 
> Thanks !

Sure, good with me, I don't think we have colliding patches.

Reviewed-by: Johannes Berg <johannes.berg@intel.com>

> As iwlwifi use fat skbs, it should not pull too much data in skb->head, and
> particularly no tcp data payload, or splice() is slower, and TCP coalescing is
> disabled. Copying payload to userland also involves at least two copies (part
> from header, part from fragment)
> 
> Each layer will pull its header from the fragment as needed.
> 
> (on 64bit arches, skb_tailroom(skb) at this point is 192 bytes)
> 
> With this patch applied, I have a major reduction of collapsed/pruned TCP
> packets, a nice increase of TCPRcvCoalesce counter, and overall better Internet
> User experience.
> 
> Small packets are still using a fragless skb, so that page can be reused by the
> driver.

We may want to move this code into mac80211 later though since it also has an if (pull in everything, even reallocating if necessary, if it's a management frame), but that can wait, I think we're the only driver using paged RX.

johannes

PS: sorry about the footer -- unfortunately I haven't managed to convince IT to remove it on my @intel address
--------------------------------------------------------------------------------------
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland 
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Douglas Lusk, Peter Gleissner, Hannes Schwaderer
Registergericht: Muenchen HRB 47456 
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052

^ permalink raw reply

* [PATCH 3/3] ethtool: Addition of -m option to dump module eeprom
From: Stuart Hodgson @ 2012-05-18 14:58 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, David Miller, Yaniv Rosner, Eilon Greenstein

The -m option now allows for retrieval of EEPROM
information form a plug in module such as SFP+. This
shows specific information about the type and
capabilities of the module in use The format can be
easily extended to support other modules types such as
QSFP in future. Raw data dump is also supported.

Signed-off-by: Stuart Hodgson <smhodgson@solarflare.com>
---
 Makefile.am    |    2 +-
 ethtool.8.in   |   10 ++
 ethtool.c      |   87 +++++++++++++
 internal.h     |    3 +
 sfpid.c        |  387 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 test-cmdline.c |   10 ++
 6 files changed, 498 insertions(+), 1 deletions(-)
 create mode 100644 sfpid.c

diff --git a/Makefile.am b/Makefile.am
index 4b0eb17..e40fc99 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,7 @@ ethtool_SOURCES = ethtool.c ethtool-copy.h internal.h \
 		  fec_8xx.c ibm_emac.c ixgb.c ixgbe.c natsemi.c	\
 		  pcnet32.c realtek.c tg3.c marvell.c vioc.c	\
 		  smsc911x.c at76c50x-usb.c sfc.c stmmac.c	\
-		  rxclass.c
+		  rxclass.c sfpid.c
 
 TESTS = test-cmdline
 check_PROGRAMS = test-cmdline test-one-cmdline
diff --git a/ethtool.8.in b/ethtool.8.in
index 63d5d48..cba86ff 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -318,6 +318,13 @@ ethtool \- query or control network driver and hardware settings
 .BN other
 .BN combined
 .HP
+.B ethtool \-m|\-\-dump\-module\-eeprom
+.I devname
+.B2 raw on off
+.B2 hex on off
+.BN offset
+.BN length
+.HP
 .B ethtool \-\-show\-priv\-flags
 .I devname
 .HP
@@ -789,6 +796,9 @@ Changes the number of channels used only for other purposes e.g. link interrupts
 .BI combined \ N
 Changes the number of multi-purpose channels.
 .TP
+.B \-m \-\-dump\-module\-eeprom
+Retrieves and if possible decodes the EEPROM from plugin modules, e.g SFP+, QSFP
+.TP
 .B \-\-show\-priv\-flags
 Queries the specified network device for its private flags.  The
 names and meanings of private flags (if any) are defined by each
diff --git a/ethtool.c b/ethtool.c
index fdc21de..d9f1462 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -3078,6 +3078,87 @@ static int do_sprivflags(struct cmd_context *ctx)
 	return 0;
 }
 
+static int do_getmodule(struct cmd_context *ctx)
+{
+	struct ethtool_modinfo modinfo;
+	struct ethtool_eeprom *eeprom;
+	u32 geeprom_offset = 0;
+	u32 geeprom_length = -1;
+	int geeprom_changed = 0;
+	int geeprom_dump_raw = 0;
+	int geeprom_dump_hex = 0;
+	int err;
+
+	struct cmdline_info cmdline_geeprom[] = {
+		{ "offset", CMDL_U32, &geeprom_offset, NULL },
+		{ "length", CMDL_U32, &geeprom_length, NULL },
+		{ "raw", CMDL_BOOL, &geeprom_dump_raw, NULL },
+		{ "hex", CMDL_BOOL, &geeprom_dump_hex, NULL },
+	};
+
+	parse_generic_cmdline(ctx, &geeprom_changed,
+			      cmdline_geeprom, ARRAY_SIZE(cmdline_geeprom));
+
+	if (geeprom_dump_raw && geeprom_dump_hex) {
+		printf("Hex and raw dump cannot be specified together\n");
+		return 1;
+	}
+
+	modinfo.cmd = ETHTOOL_GMODULEINFO;
+	err = send_ioctl(ctx, &modinfo);
+	if (err < 0) {
+		perror("Cannot get module EEPROM information");
+		return 1;
+	}
+
+	if (geeprom_length == -1)
+		geeprom_length = modinfo.eeprom_len;
+
+	if (modinfo.eeprom_len < geeprom_offset + geeprom_length)
+		geeprom_length = modinfo.eeprom_len - geeprom_offset;
+
+	eeprom = calloc(1, sizeof(*eeprom)+geeprom_length);
+	if (!eeprom) {
+		perror("Cannot allocate memory for Module EEPROM data");
+		return 1;
+	}
+
+	eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+	eeprom->len = geeprom_length;
+	eeprom->offset = geeprom_offset;
+	err = send_ioctl(ctx, eeprom);
+	if (err < 0) {
+		perror("Cannot get Module EEPROM data");
+		free(eeprom);
+		return 1;
+	}
+
+	if (geeprom_dump_raw) {
+		fwrite(eeprom->data, 1, eeprom->len, stdout);
+	} else {
+		if (eeprom->offset != 0  ||
+		    (eeprom->len != modinfo.eeprom_len)) {
+			geeprom_dump_hex = 1;
+		} else if (!geeprom_dump_hex) {
+			switch (modinfo.type) {
+			case ETH_MODULE_SFF_8079:
+			case ETH_MODULE_SFF_8472:
+				sff8079_show_all(eeprom->data);
+				break;
+			default:
+				geeprom_dump_hex = 1;
+				break;
+			}
+		}
+		if (geeprom_dump_hex)
+			dump_hex(eeprom->data, eeprom->len, eeprom->offset);
+	}
+
+	free(eeprom);
+
+	return 0;
+}
+
 int send_ioctl(struct cmd_context *ctx, void *cmd)
 {
 #ifndef TEST_ETHTOOL
@@ -3232,6 +3313,12 @@ static const struct option {
 	{ "--show-priv-flags" , 1, do_gprivflags, "Query private flags" },
 	{ "--set-priv-flags", 1, do_sprivflags, "Set private flags",
 	  "		FLAG on|off ...\n" },
+	{ "-m|--dump-module-eeprom", 1, do_getmodule,
+	  "Qeuery/Decode Module EEPROM information",
+	  "		[ raw on|off ]\n"
+	  "		[ hex on|off ]\n"
+	  "		[ offset N ]\n"
+	  "		[ length N ]\n" },
 	{ "-h|--help", 0, show_usage, "Show this help" },
 	{ "--version", 0, do_version, "Show version number" },
 	{}
diff --git a/internal.h b/internal.h
index 867c0ea..576b79b 100644
--- a/internal.h
+++ b/internal.h
@@ -174,4 +174,7 @@ int rxclass_rule_ins(struct cmd_context *ctx,
 		     struct ethtool_rx_flow_spec *fsp);
 int rxclass_rule_del(struct cmd_context *ctx, __u32 loc);
 
+/* Module EEPROM parsing code */
+void sff8079_show_all(const __u8 *id);
+
 #endif /* ETHTOOL_INTERNAL_H__ */
diff --git a/sfpid.c b/sfpid.c
new file mode 100644
index 0000000..a4a671d
--- /dev/null
+++ b/sfpid.c
@@ -0,0 +1,387 @@
+/****************************************************************************
+ * Support for Solarflare Solarstorm network controllers and boards
+ * Copyright 2010 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <stdio.h>
+#include "internal.h"
+
+static void sff8079_show_identifier(const __u8 *id)
+{
+	printf("\tIdentifier          : 0x%02x", id[0]);
+	switch (id[0]) {
+	case 0x00:
+		printf(" (no module present, unknown, or unspecified)\n");
+		break;
+	case 0x01:
+		printf(" (GBIC)\n");
+		break;
+	case 0x02:
+		printf(" (module soldered to motherboard)\n");
+		break;
+	case 0x03:
+		printf(" (SFP)\n");
+		break;
+	default:
+		 printf(" (reserved or unknown)\n");
+		break;
+	}
+}
+
+static void sff8079_show_ext_identifier(const __u8 *id)
+{
+	printf("\tExtended identifier : 0x%02x", id[1]);
+	if (id[1] == 0x00)
+		printf(" (GBIC not specified / not MOD_DEF compliant)\n");
+	else if (id[1] == 0x04)
+		printf(" (GBIC/SFP defined by 2-wire interface ID)\n");
+	else if (id[1] <= 0x07)
+		printf(" (GBIC compliant with MOD_DEF %u)\n", id[1]);
+	else
+		printf(" (unknown)\n");
+}
+
+static void sff8079_show_connector(const __u8 *id)
+{
+	printf("\tConnector           : 0x%02x", id[2]);
+	switch (id[2]) {
+	case 0x00:
+		printf(" (unknown or unspecified)\n");
+		break;
+	case 0x01:
+		printf(" (SC)\n");
+		break;
+	case 0x02:
+		printf(" (Fibre Channel Style 1 copper)\n");
+		break;
+	case 0x03:
+		printf(" (Fibre Channel Style 2 copper)\n");
+		break;
+	case 0x04:
+		printf(" (BNC/TNC)\n");
+		break;
+	case 0x05:
+		printf(" (Fibre Channel coaxial headers)\n");
+		break;
+	case 0x06:
+		printf(" (FibreJack)\n");
+		break;
+	case 0x07:
+		printf(" (LC)\n");
+		break;
+	case 0x08:
+		printf(" (MT-RJ)\n");
+		break;
+	case 0x09:
+		printf(" (MU)\n");
+		break;
+	case 0x0a:
+		printf(" (SG)\n");
+		break;
+	case 0x0b:
+		printf(" (Optical pigtail)\n");
+		break;
+	case 0x0c:
+		printf(" (MPO Parallel Optic)\n");
+		break;
+	case 0x20:
+		printf(" (HSSDC II)\n");
+		break;
+	case 0x21:
+		printf(" (Copper pigtail)\n");
+		break;
+	case 0x22:
+		printf(" (RJ45)\n");
+		break;
+	default:
+		printf(" (reserved or unknown)\n");
+		break;
+	}
+}
+
+static void sff8079_show_transceiver(const __u8 *id)
+{
+	static const char *pfx = "\t                    :  =>";
+
+	printf("\tTransceiver codes   : 0x%02x 0x%02x 0x%02x" \
+	       "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+	       id[3], id[4], id[5], id[6],
+	       id[7], id[8], id[9], id[10]);
+	/* 10G Ethernet Compliance Codes */
+	if (id[3] & (1 << 7))
+		printf("%s 10G Ethernet: 10G Base-ER" \
+		       " [SFF-8472 rev10.4 only]\n", pfx);
+	if (id[3] & (1 << 6))
+		printf("%s 10G Ethernet: 10G Base-LRM\n", pfx);
+	if (id[3] & (1 << 5))
+		printf("%s 10G Ethernet: 10G Base-LR\n", pfx);
+	if (id[3] & (1 << 4))
+		printf("%s 10G Ethernet: 10G Base-SR\n", pfx);
+	/* Infiniband Compliance Codes */
+	if (id[3] & (1 << 3))
+		printf("%s Infiniband: 1X SX\n", pfx);
+	if (id[3] & (1 << 2))
+		printf("%s Infiniband: 1X LX\n", pfx);
+	if (id[3] & (1 << 1))
+		printf("%s Infiniband: 1X Copper Active\n", pfx);
+	if (id[3] & (1 << 0))
+		printf("%s Infiniband: 1X Copper Passive\n", pfx);
+	/* ESCON Compliance Codes */
+	if (id[4] & (1 << 7))
+		printf("%s ESCON: ESCON MMF, 1310nm LED\n", pfx);
+	if (id[4] & (1 << 6))
+		printf("%s ESCON: ESCON SMF, 1310nm Laser\n", pfx);
+	/* SONET Compliance Codes */
+	if (id[4] & (1 << 5))
+		printf("%s SONET: OC-192, short reach\n", pfx);
+	if (id[4] & (1 << 4))
+		printf("%s SONET: SONET reach specifier bit 1\n", pfx);
+	if (id[4] & (1 << 3))
+		printf("%s SONET: SONET reach specifier bit 2\n", pfx);
+	if (id[4] & (1 << 2))
+		printf("%s SONET: OC-48, long reach\n", pfx);
+	if (id[4] & (1 << 1))
+		printf("%s SONET: OC-48, intermediate reach\n", pfx);
+	if (id[4] & (1 << 0))
+		printf("%s SONET: OC-48, short reach\n", pfx);
+	if (id[5] & (1 << 6))
+		printf("%s SONET: OC-12, single mode, long reach\n", pfx);
+	if (id[5] & (1 << 5))
+		printf("%s SONET: OC-12, single mode, inter. reach\n", pfx);
+	if (id[5] & (1 << 4))
+		printf("%s SONET: OC-12, short reach\n", pfx);
+	if (id[5] & (1 << 2))
+		printf("%s SONET: OC-3, single mode, long reach\n", pfx);
+	if (id[5] & (1 << 1))
+		printf("%s SONET: OC-3, single mode, inter. reach\n", pfx);
+	if (id[5] & (1 << 0))
+		printf("%s SONET: OC-3, short reach\n", pfx);
+	/* Ethernet Compliance Codes */
+	if (id[6] & (1 << 7))
+		printf("%s Ethernet: BASE-PX\n", pfx);
+	if (id[6] & (1 << 6))
+		printf("%s Ethernet: BASE-BX10\n", pfx);
+	if (id[6] & (1 << 5))
+		printf("%s Ethernet: 100BASE-FX\n", pfx);
+	if (id[6] & (1 << 4))
+		printf("%s Ethernet: 100BASE-LX/LX10\n", pfx);
+	if (id[6] & (1 << 3))
+		printf("%s Ethernet: 1000BASE-T\n", pfx);
+	if (id[6] & (1 << 2))
+		printf("%s Ethernet: 1000BASE-CX\n", pfx);
+	if (id[6] & (1 << 1))
+		printf("%s Ethernet: 1000BASE-LX\n", pfx);
+	if (id[6] & (1 << 0))
+		printf("%s Ethernet: 1000BASE-SX\n", pfx);
+	/* Fibre Channel link length */
+	if (id[7] & (1 << 7))
+		printf("%s FC: very long distance (V)\n", pfx);
+	if (id[7] & (1 << 6))
+		printf("%s FC: short distance (S)\n", pfx);
+	if (id[7] & (1 << 5))
+		printf("%s FC: intermediate distance (I)\n", pfx);
+	if (id[7] & (1 << 4))
+		printf("%s FC: long distance (L)\n", pfx);
+	if (id[7] & (1 << 3))
+		printf("%s FC: medium distance (M)\n", pfx);
+	/* Fibre Channel transmitter technology */
+	if (id[7] & (1 << 2))
+		printf("%s FC: Shortwave laser, linear Rx (SA)\n", pfx);
+	if (id[7] & (1 << 1))
+		printf("%s FC: Longwave laser (LC)\n", pfx);
+	if (id[7] & (1 << 0))
+		printf("%s FC: Electrical inter-enclosure (EL)\n", pfx);
+	if (id[8] & (1 << 7))
+		printf("%s FC: Electrical intra-enclosure (EL)\n", pfx);
+	if (id[8] & (1 << 6))
+		printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx);
+	if (id[8] & (1 << 5))
+		printf("%s FC: Shortwave laser with OFC (SL)\n", pfx);
+	if (id[8] & (1 << 4))
+		printf("%s FC: Longwave laser (LL)\n", pfx);
+	if (id[8] & (1 << 3))
+		printf("%s FC: Copper Active\n", pfx);
+	if (id[8] & (1 << 2))
+		printf("%s FC: Copper Passive\n", pfx);
+	if (id[8] & (1 << 1))
+		printf("%s FC: Copper FC-BaseT\n", pfx);
+	/* Fibre Channel transmission media */
+	if (id[9] & (1 << 7))
+		printf("%s FC: Twin Axial Pair (TW)\n", pfx);
+	if (id[9] & (1 << 6))
+		printf("%s FC: Twisted Pair (TP)\n", pfx);
+	if (id[9] & (1 << 5))
+		printf("%s FC: Miniature Coax (MI)\n", pfx);
+	if (id[9] & (1 << 4))
+		printf("%s FC: Video Coax (TV)\n", pfx);
+	if (id[9] & (1 << 3))
+		printf("%s FC: Multimode, 62.5um (M6)\n", pfx);
+	if (id[9] & (1 << 2))
+		printf("%s FC: Multimode, 50um (M5)\n", pfx);
+	if (id[9] & (1 << 0))
+		printf("%s FC: Single Mode (SM)\n", pfx);
+	/* Fibre Channel speed */
+	if (id[10] & (1 << 7))
+		printf("%s FC: 1200 MBytes/sec\n", pfx);
+	if (id[10] & (1 << 6))
+		printf("%s FC: 800 MBytes/sec\n", pfx);
+	if (id[10] & (1 << 4))
+		printf("%s FC: 400 MBytes/sec\n", pfx);
+	if (id[10] & (1 << 2))
+		printf("%s FC: 200 MBytes/sec\n", pfx);
+	if (id[10] & (1 << 0))
+		printf("%s FC: 100 MBytes/sec\n", pfx);
+}
+
+static void sff8079_show_encoding(const __u8 *id)
+{
+	printf("\tEncoding            : 0x%02x", id[11]);
+	switch (id[11]) {
+	case 0x00:
+		printf(" (unspecified)\n");
+		break;
+	case 0x01:
+		printf(" (8B/10B)\n");
+		break;
+	case 0x02:
+		printf(" (4B/5B)\n");
+		break;
+	case 0x03:
+		printf(" (NRZ)\n");
+		break;
+	case 0x04:
+		printf(" (Manchester)\n");
+		break;
+	case 0x05:
+		printf(" (SONET Scrambled)\n");
+		break;
+	case 0x06:
+		printf(" (64B/66B)\n");
+		break;
+	default:
+		printf(" (reserved or unknown)\n");
+		break;
+	}
+}
+
+static void sff8079_show_rate_identifier(const __u8 *id)
+{
+	printf("\tRate identifier     : 0x%02x", id[13]);
+	switch (id[13]) {
+	case 0x00:
+		printf(" (unspecified)\n");
+		break;
+	case 0x01:
+		printf(" (4/2/1G Rate_Select & AS0/AS1)\n");
+		break;
+	case 0x02:
+		printf(" (8/4/2G Rx Rate_Select only)\n");
+		break;
+	case 0x03:
+		printf(" (8/4/2G Independent Rx & Tx Rate_Select)\n");
+		break;
+	case 0x04:
+		printf(" (8/4/2G Tx Rate_Select only)\n");
+		break;
+	default:
+		printf(" (reserved or unknown)\n");
+		break;
+	}
+}
+
+static void sff8079_show_oui(const __u8 *id)
+{
+	printf("\tVendor OUI          : %02x:%02x:%02x\n",
+	       id[37], id[38], id[39]);
+}
+
+static void sff8079_show_wavelength_or_copper_compliance(const __u8 *id)
+{
+	if (id[8] & (1 << 2)) {
+		printf("\tPassive Cu cmplnce. : 0x%02x", id[60]);
+		switch (id[60]) {
+		case 0x00:
+			printf(" (unspecified)");
+			break;
+		case 0x01:
+			printf(" (SFF-8431 appendix E)");
+			break;
+		default:
+			printf(" (unknown)");
+			break;
+		}
+		printf(" [SFF-8472 rev10.4 only]\n");
+	} else if (id[8] & (1 << 3)) {
+		printf("\tActive Cu cmplnce.  : 0x%02x", id[60]);
+		switch (id[60]) {
+		case 0x00:
+			printf(" (unspecified)");
+			break;
+		case 0x01:
+			printf(" (SFF-8431 appendix E)");
+			break;
+		case 0x04:
+			printf(" (SFF-8431 limiting)");
+			break;
+		default:
+			printf(" (unknown)");
+			break;
+		}
+		printf(" [SFF-8472 rev10.4 only]\n");
+	} else {
+		printf("\tLaser wavelength    : %unm\n",
+		       (id[60] << 8) | id[61]);
+	}
+}
+
+static void sff8079_show_value_with_unit(const __u8 *id, unsigned int reg,
+					 const char *name, unsigned int mult,
+					 const char *unit)
+{
+	unsigned int val = id[reg];
+
+	printf("\t%-20s: %u%s\n", name, val * mult, unit);
+}
+
+static void sff8079_show_ascii(const __u8 *id, unsigned int first_reg,
+			       unsigned int last_reg, const char *name)
+{
+	unsigned int reg, val;
+
+	printf("\t%-20s: ", name);
+	for (reg = first_reg; reg <= last_reg; reg++) {
+		val = id[reg];
+		putchar(((val >= 32) && (val <= 126)) ? val : '_');
+	}
+	printf("\n");
+}
+
+void sff8079_show_all(const __u8 *id)
+{
+	sff8079_show_identifier(id);
+	if ((id[0] == 0x03) && (id[1] == 0x04)) {
+		sff8079_show_ext_identifier(id);
+		sff8079_show_connector(id);
+		sff8079_show_transceiver(id);
+		sff8079_show_encoding(id);
+		sff8079_show_value_with_unit(id, 12, "BR, Nominal", 100, "MBd");
+		sff8079_show_rate_identifier(id);
+		sff8079_show_value_with_unit(id, 14,
+					     "Length (SMF,km)", 1, "km");
+		sff8079_show_value_with_unit(id, 15, "Length (SMF)", 100, "m");
+		sff8079_show_value_with_unit(id, 16, "Length (50um)", 10, "m");
+		sff8079_show_value_with_unit(id, 17,
+					     "Length (62.5um)", 10, "m");
+		sff8079_show_value_with_unit(id, 18, "Length (Copper)", 1, "m");
+		sff8079_show_value_with_unit(id, 19, "Length (OM3)", 10, "m");
+		sff8079_show_wavelength_or_copper_compliance(id);
+		sff8079_show_ascii(id, 20, 35, "Vendor name");
+		sff8079_show_oui(id);
+		sff8079_show_ascii(id, 40, 55, "Vendor PN");
+		sff8079_show_ascii(id, 56, 59, "Vendor rev");
+	}
+}
diff --git a/test-cmdline.c b/test-cmdline.c
index 4718842..f830d54 100644
--- a/test-cmdline.c
+++ b/test-cmdline.c
@@ -210,6 +210,16 @@ static struct test_case {
 	{ 0, "--show-priv-flags devname" },
 	{ 1, "--show-priv-flags devname foo" },
 	{ 1, "--show-priv-flags" },
+	{ 1, "-m" },
+	{ 0, "-m devname" },
+	{ 1, "--dump-module-eeprom" },
+	{ 0, "--dump-module-eeprom devname" },
+	{ 0, "-m devname raw on" },
+	{ 0, "-m devname raw off" },
+	{ 0, "-m devname hex on" },
+	{ 0, "-m devname hex off" },
+	{ 1, "-m devname hex on raw on" },
+	{ 0, "-m devname offset 4 length 6" },
 	/* can't test --set-priv-flags yet */
 	{ 0, "-h" },
 	{ 0, "--help" },
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 2/3] ethtool: Update ethtool-copy.h to support module eeprom retrieval
From: Stuart Hodgson @ 2012-05-18 14:58 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Yaniv Rosner, David Miller, netdev, Eilon Greenstein

Signed-off-by: Stuart Hodgson <smhodgson@solarflare.com>
---
 ethtool-copy.h |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index d904c1a..9e26a76 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -27,10 +27,15 @@ struct ethtool_cmd {
 				 * access it */
 	__u8	duplex;		/* Duplex, half or full */
 	__u8	port;		/* Which connector port */
-	__u8	phy_address;
+	__u8	phy_address;	/* MDIO PHY address (PRTAD for clause 45).
+				 * May be read-only or read-write
+				 * depending on the driver.
+				 */
 	__u8	transceiver;	/* Which transceiver to use */
 	__u8	autoneg;	/* Enable or disable autonegotiation */
-	__u8	mdio_support;
+	__u8	mdio_support;	/* MDIO protocols supported.  Read-only.
+				 * Not set by all drivers.
+				 */
 	__u32	maxtxpkt;	/* Tx pkts before generating tx int */
 	__u32	maxrxpkt;	/* Rx pkts before generating rx int */
 	__u16	speed_hi;       /* The forced speed (upper
@@ -56,6 +61,20 @@ static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
 	return (ep->speed_hi << 16) | ep->speed;
 }
 
+/* Device supports clause 22 register access to PHY or peripherals
+ * using the interface defined in <linux/mii.h>.  This should not be
+ * set if there are known to be no such peripherals present or if
+ * the driver only emulates clause 22 registers for compatibility.
+ */
+#define ETH_MDIO_SUPPORTS_C22	1
+
+/* Device supports clause 45 register access to PHY or peripherals
+ * using the interface defined in <linux/mii.h> and <linux/mdio.h>.
+ * This should not be set if there are known to be no such peripherals
+ * present.
+ */
+#define ETH_MDIO_SUPPORTS_C45	2
+
 #define ETHTOOL_FWVERS_LEN	32
 #define ETHTOOL_BUSINFO_LEN	32
 /* these strings are set to whatever the driver author decides... */
@@ -115,6 +134,23 @@ struct ethtool_eeprom {
 };
 
 /**
+ * struct ethtool_modinfo - plugin module eeprom information
+ * @cmd: %ETHTOOL_GMODULEINFO
+ * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx
+ * @eeprom_len: Length of the eeprom
+ *
+ * This structure is used to return the information to
+ * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM.
+ * The type code indicates the eeprom data format
+ */
+struct ethtool_modinfo {
+	__u32   cmd;
+	__u32   type;
+	__u32   eeprom_len;
+	__u32   reserved[8];
+};
+
+/**
  * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates
  * @cmd: ETHTOOL_{G,S}COALESCE
  * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
@@ -680,6 +716,29 @@ struct ethtool_sfeatures {
 	struct ethtool_set_features_block features[0];
 };
 
+/**
+ * struct ethtool_ts_info - holds a device's timestamping and PHC association
+ * @cmd: command number = %ETHTOOL_GET_TS_INFO
+ * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags
+ * @phc_index: device index of the associated PHC, or -1 if there is none
+ * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values
+ * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values
+ *
+ * The bits in the 'tx_types' and 'rx_filters' fields correspond to
+ * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values,
+ * respectively.  For example, if the device supports HWTSTAMP_TX_ON,
+ * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set.
+ */
+struct ethtool_ts_info {
+	__u32	cmd;
+	__u32	so_timestamping;
+	__s32	phc_index;
+	__u32	tx_types;
+	__u32	tx_reserved[3];
+	__u32	rx_filters;
+	__u32	rx_reserved[3];
+};
+
 /*
  * %ETHTOOL_SFEATURES changes features present in features[].valid to the
  * values of corresponding bits in features[].requested. Bits in .requested
@@ -786,6 +845,9 @@ enum ethtool_sfeatures_retval_bits {
 #define ETHTOOL_SET_DUMP	0x0000003e /* Set dump settings */
 #define ETHTOOL_GET_DUMP_FLAG	0x0000003f /* Get dump settings */
 #define ETHTOOL_GET_DUMP_DATA	0x00000040 /* Get dump data */
+#define ETHTOOL_GET_TS_INFO	0x00000041 /* Get time stamping and PHC info */
+#define ETHTOOL_GMODULEINFO	0x00000042 /* Get plug-in module information */
+#define ETHTOOL_GMODULEEEPROM	0x00000043 /* Get plug-in module eeprom */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
@@ -935,6 +997,12 @@ enum ethtool_sfeatures_retval_bits {
 #define RX_CLS_LOC_FIRST	0xfffffffe
 #define RX_CLS_LOC_LAST		0xfffffffd
 
+/* EEPROM Standards for plug in modules */
+#define ETH_MODULE_SFF_8079		0x1
+#define ETH_MODULE_SFF_8079_LEN		256
+#define ETH_MODULE_SFF_8472		0x2
+#define ETH_MODULE_SFF_8472_LEN		512
+
 /* Reset flags */
 /* The reset() operation must clear the flags for the components which
  * were actually reset.  On successful return, the flags indicate the
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 1/3] ethtool: Split out printing of hex data
From: Stuart Hodgson @ 2012-05-18 14:58 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, Yaniv Rosner, David Miller, Eilon Greenstein

Split out printing of hex data to common function from
dump_regs and dump_eeprom. Ready for use by module
eeprom dumping.

Signed-off-by: Stuart Hodgson <smhodgson@solarflare.com>
---
 ethtool.c |   35 ++++++++++++++++++-----------------
 1 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/ethtool.c b/ethtool.c
index e80b38b..fdc21de 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -787,6 +787,20 @@ static const struct {
 	{ "st_gmac", st_gmac_dump_regs },
 };
 
+static void dump_hex(__u8 *data, int len, int offset)
+{
+	int i;
+
+	fprintf(stdout, "Offset\tValues\n");
+	fprintf(stdout, "--------\t-----");
+	for (i = 0; i < len; i++) {
+		if (i%16 == 0)
+			fprintf(stdout, "\n0x%04x:\t", i + offset);
+		fprintf(stdout, " %02x", data[i]);
+	}
+	fprintf(stdout, "\n\n");
+}
+
 static int dump_regs(int gregs_dump_raw, int gregs_dump_hex,
 		     const char *gregs_dump_file,
 		     struct ethtool_drvinfo *info, struct ethtool_regs *regs)
@@ -820,22 +834,14 @@ static int dump_regs(int gregs_dump_raw, int gregs_dump_hex,
 				     ETHTOOL_BUSINFO_LEN))
 				return driver_list[i].func(info, regs);
 
-	fprintf(stdout, "Offset\tValues\n");
-	fprintf(stdout, "--------\t-----");
-	for (i = 0; i < regs->len; i++) {
-		if (i%16 == 0)
-			fprintf(stdout, "\n%03x:\t", i);
-		fprintf(stdout, " %02x", regs->data[i]);
-	}
-	fprintf(stdout, "\n\n");
+	dump_hex(regs->data, regs->len, 0);
+
 	return 0;
 }
 
 static int dump_eeprom(int geeprom_dump_raw, struct ethtool_drvinfo *info,
 		       struct ethtool_eeprom *ee)
 {
-	int i;
-
 	if (geeprom_dump_raw) {
 		fwrite(ee->data, 1, ee->len, stdout);
 		return 0;
@@ -847,13 +853,8 @@ static int dump_eeprom(int geeprom_dump_raw, struct ethtool_drvinfo *info,
 		return tg3_dump_eeprom(info, ee);
 	}
 
-	fprintf(stdout, "Offset\t\tValues\n");
-	fprintf(stdout, "------\t\t------");
-	for (i = 0; i < ee->len; i++) {
-		if(!(i%16)) fprintf(stdout, "\n0x%04x\t\t", i + ee->offset);
-		fprintf(stdout, "%02x ", ee->data[i]);
-	}
-	fprintf(stdout, "\n");
+	dump_hex(ee->data, ee->len, ee->offset);
+
 	return 0;
 }
 
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 0/3] ethtool: Add command to dump and parse module EEPROM
From: Stuart Hodgson @ 2012-05-18 14:57 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Yaniv Rosner, David Miller, netdev, Eilon Greenstein

These three patches add support for the new ETHTOOL_GMODULEINFO and 
ETHTOOL_GMODULEEEPROM commands in net-next.

The first patch splits duplicated code used to print hex data into a function
The second patch updates the the ethtool-copy.h from the net-next. 
The third implements the new commands. Support for parsing SFP 8079 compatible EEPROMs
has also be incorporated.

Stu

^ permalink raw reply

* [PATCH net-next] iwlwifi: dont pull too much payload in skb head
From: Eric Dumazet @ 2012-05-18 14:48 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Johannes Berg, Wey-Yi Guy

From: Eric Dumazet <edumazet@google.com>

Since merge window is now pretty close, I would prefer David applies
this directly in net-next, if you dont mind, as this patch is more a
core network issue than an iwlwifi one.

Thanks !

[PATCH net-next] iwlwifi: dont pull too much payload in skb head

As iwlwifi use fat skbs, it should not pull too much data in skb->head,
and particularly no tcp data payload, or splice() is slower, and TCP
coalescing is disabled. Copying payload to userland also involves at
least two copies (part from header, part from fragment)

Each layer will pull its header from the fragment as needed.

(on 64bit arches, skb_tailroom(skb) at this point is 192 bytes)

With this patch applied, I have a major reduction of collapsed/pruned
TCP packets, a nice increase of TCPRcvCoalesce counter, and overall
better Internet User experience.

Small packets are still using a fragless skb, so that page can be reused
by the driver.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Johannes Berg <johannes.berg@intel.com>
Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-rx.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 18a3837..403de96 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -759,7 +759,12 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
 		IWL_ERR(priv, "alloc_skb failed\n");
 		return;
 	}
-	hdrlen = min_t(unsigned int, len, skb_tailroom(skb));
+	/* If frame is small enough to fit in skb->head, pull it completely.
+	 * If not, only pull ieee80211_hdr so that splice() or TCP coalesce
+	 * are more efficient.
+	 */
+	hdrlen = (len <= skb_tailroom(skb)) ? len : sizeof(*hdr);
+
 	memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
 	fraglen = len - hdrlen;
 

^ permalink raw reply related

* Re: Strange latency spikes/TX network stalls on Sun Fire X4150(x86) and e1000e
From: Denys Fedoryshchenko @ 2012-05-18 14:04 UTC (permalink / raw)
  To: netdev, e1000-devel, jeffrey.t.kirsher, jesse.brandeburg,
	therbert, eric.dumazet, davem
In-Reply-To: <df211722d18136698aeeda2f17b876e2@visp.net.lb>

It seems logic in BQL has serious issues. The most bad thing, if 
someone don't want limits (especially low as this),
there is no way to disable BQL in Kernel configuration, only tuning 
each interface over sysfs values.

I just did short debug:
if (limit != dql->limit) {
+                printk("New limit %d\n", dql->limit);
                 dql->limit = limit;
                 ovlimit = 0;
}

And got this numbers:
[   18.696839] New limit 0
[   19.622967] New limit 42
[   20.037810] New limit 165
[   35.473666] New limit 386
[   37.418591] New limit 1374
[   37.420064] New limit 6432
[   39.209480] New limit 16548
[   39.214773] New limit 1704
[   40.696065] New limit 6762
[   40.696390] New limit 15564
[   41.921120] New limit 25788
[   41.921165] New limit 388
[   42.696286] New limit 534
[   42.696539] New limit 1096
[   42.696719] New limit 2304
[   53.360394] New limit 24334
[   54.696072] New limit 484
[   54.696135] New limit 934

This means sometimes limit goes below MTU, and till queue limit 
increased, i will see this traffic "stalled",
if there is large packet in queue. Probably BQL miscalculate queue as 
full because of some specific handling
of sent packets in e1000e on this specific hardware. Because it should 
not be full, it is 1Gbps wire,
and it is empty. So in result, instead of eliminating latency, it is 
adding it.

I can make a patch that will make minimum BQL value not less than MTU + 
overhead, is it ok like this?
Probably it will solve issue, but it is more workaround and safety 
fuse, than a solution.

On 2012-05-17 19:54, Denys Fedoryshchenko wrote:
> Also i notice, limit constantly changing over time (even i am not
> touching it).
>
> centaur ~ # grep "" 
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/*
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/hold_time:1000
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/inflight:0
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit:13018
> 
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit_max:1879048192
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit_min:0
> centaur ~ # grep "" 
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/*
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/hold_time:1000
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/inflight:4542
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit:13018
> 
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit_max:1879048192
> /sys/class/net/eth0/queues/tx-0/byte_queue_limits/limit_min:0
>
> Is it supposed to be like this?
>
> On 2012-05-17 16:42, Denys Fedoryshchenko wrote:
>> Found commit that cause problem:
>>
>> author	Tom Herbert <therbert@google.com>
>> Mon, 28 Nov 2011 16:33:16 +0000 (16:33 +0000)
>> committer	David S. Miller <davem@davemloft.net>
>> Tue, 29 Nov 2011 17:46:19 +0000 (12:46 -0500)
>> commit	3f0cfa3bc11e7f00c9994e0f469cbc0e7da7b00c
>> tree	d6670a4f94b2b9dedacc38edb6f0e1306b889f6b	tree | snapshot
>> parent	114cf5802165ee93e3ab461c9c505cd94a08b800	commit | diff
>> e1000e: Support for byte queue limits
>>
>> Changes to e1000e to use byte queue limits.
>>
>> Signed-off-by: Tom Herbert <therbert@google.com>
>> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
>> Signed-off-by: David S. Miller <davem@davemloft.net>
>>
>> If i reverse it, problem disappearing.
>>
>> How i reproduce it:
>> In two consoles do "fast" ping to nearby host
>> ping 194.146.XXX.XXX -s1472 -i0.0001
>> ping 194.146.XXX.XXX -s1472 -i0.1
>>
>> For third open ssh to host with "problem", open mcedit, and just
>> scroll down large text file.
>> After few seconds some "stalls" will occur, and in ping history i 
>> can see:
>> 1480 bytes from 194.146.153.7: icmp_req=1797 ttl=64 time=0.161 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1798 ttl=64 time=0.198 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1799 ttl=64 time=0.340 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1800 ttl=64 time=0.381 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1801 ttl=64 time=914 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1802 ttl=64 time=804 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1803 ttl=64 time=704 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1804 ttl=64 time=594 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1805 ttl=64 time=0.287 ms
>> 1480 bytes from 194.146.153.7: icmp_req=1806 ttl=64 time=0.226 ms
>>
>>
>> If i apply small patch - problem will disappear. Sure it is not a
>> solution, but
>> let me know how i can help to debug problem more.
>>
>> --- netdev.c    2012-05-12 20:08:37.000000000 +0300
>> +++ netdev.c.patched    2012-05-17 16:32:28.895760472 +0300
>> @@ -1135,7 +1135,7 @@
>>
>>         tx_ring->next_to_clean = i;
>>
>> -       netdev_completed_queue(netdev, pkts_compl, bytes_compl);
>> +//     netdev_completed_queue(netdev, pkts_compl, bytes_compl);
>>
>>  #define TX_WAKE_THRESHOLD 32
>>         if (count && netif_carrier_ok(netdev) &&
>> @@ -2263,7 +2263,7 @@
>>                 e1000_put_txbuf(adapter, buffer_info);
>>         }
>>
>> -       netdev_reset_queue(adapter->netdev);
>> +//     netdev_reset_queue(adapter->netdev);
>>         size = sizeof(struct e1000_buffer) * tx_ring->count;
>>         memset(tx_ring->buffer_info, 0, size);
>>
>> @@ -5056,7 +5056,7 @@
>>         /* if count is 0 then mapping error has occurred */
>>         count = e1000_tx_map(adapter, skb, first, max_per_txd,
>> nr_frags, mss);
>>         if (count) {
>> -               netdev_sent_queue(netdev, skb->len);
>> +//             netdev_sent_queue(netdev, skb->len);
>>                 e1000_tx_queue(adapter, tx_flags, count);
>>                 /* Make sure there is space in the ring for the next 
>> send. */
>>                 e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2);
>>
>>
>>
>> On 2012-05-15 17:15, Denys Fedoryshchenko wrote:
>>> Hi
>>>
>>> I have two identical servers, Sun Fire X4150, both has different
>>> flavors of Linux, x86_64 and i386.
>>> 04:00.0 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit
>>> Ethernet Controller (Copper) (rev 01)
>>> 04:00.1 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit
>>> Ethernet Controller (Copper) (rev 01)
>>> 0b:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit
>>> Ethernet Controller (rev 06)
>>> 0b:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit
>>> Ethernet Controller (rev 06)
>>> I am using now interface:
>>> #ethtool -i eth0
>>> driver: e1000e
>>> version: 1.9.5-k
>>> firmware-version: 2.1-11
>>> bus-info: 0000:04:00.0
>>> There is 2 CPU , Intel(R) Xeon(R) CPU           E5440  @ 2.83GHz .
>>>
>>> i386 was acting as NAT and shaper, and as soon as i removed shaper
>>> from it, i started to experience strange lockups, e.g. traffic is
>>> normal for 5-30 seconds, then short lockup for 500-3000ms (usually
>>> around 1000ms) with dropped packets counter increasing. I was
>>> suspecting it is due load, but it seems was wrong.
>>> Recently, on another server, x86_64 i am using as development, i
>>> upgrade kernel (it was old, from 2.6 series) and on completely idle
>>> machine started to experience same latency spikes, while i am just
>>> running mc and for example typing in text editor - i notice 
>>> "stalls".
>>> After i investigate it a little more, i notice also small amount of
>>> drops on interface. No tcpdump running. Also this machine is idle, 
>>> and
>>> the only traffic there - some small broadcasts from network, my 
>>> ssh,
>>> and ping.
>>>
>>> Dropped packets in ifconfig
>>>           RX packets:3752868 errors:0 dropped:5350 overruns:0 
>>> frame:0
>>> Counter is increasing sometimes, when this stall happening.
>>>
>>> ethtool -S is clean, there is no dropped packets.
>>>
>>> I did tried to check load (mpstat and perf), there is nothing
>>> suspicious, latencytop also doesn't show anything suspicious.
>>> dropwatch report a lot of drops, but mostly because there is some
>>> broadcasts and etc. tcpdump at the moment of such drops doesn't 
>>> show
>>> anything suspicious.
>>> Changed qdisc from default fifo_fast to bfifo, without any result.
>>> Tried:  ethtool -K eth0 tso off gso off gro off sg off , no result
>>> Problem occured at 3.3.6 - 3.4.0-rc7, most probably 3.3.0 also, but 
>>> i
>>> don't remember for sure. I thik on some kernels like 3.1 probably 
>>> it
>>> doesn't occur, i will check it soon, because it is not always 
>>> reliable
>>> to reproduce it. All tests i did on 3.4.0-rc7.
>>>
>>> I did run also in background tcpdump, additionally iptables with
>>> timestamps, and at time when stall occured, seems i am still 
>>> receiving
>>> packets properly, also on iperf udp  (from some host to this 
>>> SunFire)
>>> at this moments no packets missing. But i am sure RX interface 
>>> errors
>>> are increasing.
>>> If i do iperf from SunFire to test host - there is packetloss at
>>> moments when stall occured.
>>>
>>> I suspect that by some reason network card stop to transmit, but
>>> unable to pinpoint issue. All other hosts in this network are fine 
>>> and
>>> don't have such problems.
>>> Can you help me with that please? Maybe i can provide more debug
>>> information, compile with patches and etc. Also i will try to 
>>> fallback
>>> to 3.1 and 3.0 kernels.
>>>
>>> Here it is how it occurs and i am reproducing it:
>>> I'm just opening file, and start to scroll it in mc, then in 
>>> another
>>> console i run ping
>>> [1337089061.844167] 1480 bytes from 194.146.153.20: icmp_req=162
>>> ttl=64 time=0.485 ms
>>> [1337089061.944138] 1480 bytes from 194.146.153.20: icmp_req=163
>>> ttl=64 time=0.470 ms
>>> [1337089062.467759] 1480 bytes from 194.146.153.20: icmp_req=164
>>> ttl=64 time=424 ms
>>> [1337089062.467899] 1480 bytes from 194.146.153.20: icmp_req=165
>>> ttl=64 time=324 ms
>>> [1337089062.468058] 1480 bytes from 194.146.153.20: icmp_req=166
>>> ttl=64 time=214 ms
>>> [1337089062.468161] 1480 bytes from 194.146.153.20: icmp_req=167
>>> ttl=64 time=104 ms
>>> [1337089062.468958] 1480 bytes from 194.146.153.20: icmp_req=168
>>> ttl=64 time=1.15 ms
>>> [1337089062.568604] 1480 bytes from 194.146.153.20: icmp_req=169
>>> ttl=64 time=0.477 ms
>>> [1337089062.668909] 1480 bytes from 194.146.153.20: icmp_req=170
>>> ttl=64 time=0.667 ms
>>>
>>> Remote host tcpdump:
>>> 1337089061.934737 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 163, length 1480
>>> 1337089062.458360 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 164, length 1480
>>> 1337089062.458380 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 164, length 1480
>>> 1337089062.458481 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 165, length 1480
>>> 1337089062.458502 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 165, length 1480
>>> 1337089062.458606 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 166, length 1480
>>> 1337089062.458623 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 166, length 1480
>>> 1337089062.458729 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 167, length 1480
>>> 1337089062.458745 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 167, length 1480
>>> 1337089062.459537 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 168, length 1480
>>> 1337089062.459545 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 168, length 1480
>>>
>>> Local host(SunFire) tcpdump:
>>> 1337089061.844140 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 162, length 1480
>>> 1337089061.943661 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 163, length 1480
>>> 1337089061.944124 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 163, length 1480
>>> 1337089062.465622 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 164, length 1480
>>> 1337089062.465630 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 165, length 1480
>>> 1337089062.465632 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 166, length 1480
>>> 1337089062.465634 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 167, length 1480
>>> 1337089062.467730 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 164, length 1480
>>> 1337089062.467785 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 168, length 1480
>>> 1337089062.467884 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 165, length 1480
>>> 1337089062.468035 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 166, length 1480
>>> 1337089062.468129 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 167, length 1480
>>> 1337089062.468928 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 168, length 1480
>>> 1337089062.568112 IP 194.146.153.22 > 194.146.153.20: ICMP echo
>>> request, id 3486, seq 169, length 1480
>>> 1337089062.568578 IP 194.146.153.20 > 194.146.153.22: ICMP echo
>>> reply, id 3486, seq 169, length 1480
>>>
>>> lspci -t
>>> centaur src # lspci -t
>>> -[0000:00]-+-00.0
>>>            +-02.0-[01-05]--+-00.0-[02-04]--+-00.0-[03]--
>>>            |               |               \-02.0-[04]--+-00.0
>>>            |               |                            \-00.1
>>>            |               \-00.3-[05]--
>>>            +-03.0-[06]--
>>>            +-04.0-[07]----00.0
>>>            +-05.0-[08]--
>>>            +-06.0-[09]--
>>>            +-07.0-[0a]--
>>>            +-08.0
>>>            +-10.0
>>>            +-10.1
>>>            +-10.2
>>>            +-11.0
>>>            +-13.0
>>>            +-15.0
>>>            +-16.0
>>>            +-1c.0-[0b]--+-00.0
>>>            |            \-00.1
>>>            +-1d.0
>>>            +-1d.1
>>>            +-1d.2
>>>            +-1d.3
>>>            +-1d.7
>>>            +-1e.0-[0c]----05.0
>>>            +-1f.0
>>>            +-1f.1
>>>            +-1f.2
>>>            \-1f.3
>>> lspci
>>> 00:00.0 Host bridge: Intel Corporation 5000P Chipset Memory
>>> Controller Hub (rev b1)
>>> 00:02.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI 
>>> Express
>>> x4 Port 2 (rev b1)
>>> 00:03.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI 
>>> Express
>>> x4 Port 3 (rev b1)
>>> 00:04.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI 
>>> Express
>>> x8 Port 4-5 (rev b1)
>>> 00:05.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI 
>>> Express
>>> x4 Port 5 (rev b1)
>>> 00:06.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI 
>>> Express
>>> x8 Port 6-7 (rev b1)
>>> 00:07.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI 
>>> Express
>>> x4 Port 7 (rev b1)
>>> 00:08.0 System peripheral: Intel Corporation 5000 Series Chipset 
>>> DMA
>>> Engine (rev b1)
>>> 00:10.0 Host bridge: Intel Corporation 5000 Series Chipset FSB
>>> Registers (rev b1)
>>> 00:10.1 Host bridge: Intel Corporation 5000 Series Chipset FSB
>>> Registers (rev b1)
>>> 00:10.2 Host bridge: Intel Corporation 5000 Series Chipset FSB
>>> Registers (rev b1)
>>> 00:11.0 Host bridge: Intel Corporation 5000 Series Chipset Reserved
>>> Registers (rev b1)
>>> 00:13.0 Host bridge: Intel Corporation 5000 Series Chipset Reserved
>>> Registers (rev b1)
>>> 00:15.0 Host bridge: Intel Corporation 5000 Series Chipset FBD
>>> Registers (rev b1)
>>> 00:16.0 Host bridge: Intel Corporation 5000 Series Chipset FBD
>>> Registers (rev b1)
>>> 00:1c.0 PCI bridge: Intel Corporation 631xESB/632xESB/3100 Chipset
>>> PCI Express Root Port 1 (rev 09)
>>> 00:1d.0 USB controller: Intel Corporation 631xESB/632xESB/3100
>>> Chipset UHCI USB Controller #1 (rev 09)
>>> 00:1d.1 USB controller: Intel Corporation 631xESB/632xESB/3100
>>> Chipset UHCI USB Controller #2 (rev 09)
>>> 00:1d.2 USB controller: Intel Corporation 631xESB/632xESB/3100
>>> Chipset UHCI USB Controller #3 (rev 09)
>>> 00:1d.3 USB controller: Intel Corporation 631xESB/632xESB/3100
>>> Chipset UHCI USB Controller #4 (rev 09)
>>> 00:1d.7 USB controller: Intel Corporation 631xESB/632xESB/3100
>>> Chipset EHCI USB2 Controller (rev 09)
>>> 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev d9)
>>> 00:1f.0 ISA bridge: Intel Corporation 631xESB/632xESB/3100 Chipset
>>> LPC Interface Controller (rev 09)
>>> 00:1f.1 IDE interface: Intel Corporation 631xESB/632xESB IDE
>>> Controller (rev 09)
>>> 00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA 
>>> AHCI
>>> Controller (rev 09)
>>> 00:1f.3 SMBus: Intel Corporation 631xESB/632xESB/3100 Chipset SMBus
>>> Controller (rev 09)
>>> 01:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express
>>> Upstream Port (rev 01)
>>> 01:00.3 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
>>> to
>>> PCI-X Bridge (rev 01)
>>> 02:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express
>>> Downstream Port E1 (rev 01)
>>> 02:02.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express
>>> Downstream Port E3 (rev 01)
>>> 04:00.0 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit
>>> Ethernet Controller (Copper) (rev 01)
>>> 04:00.1 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit
>>> Ethernet Controller (Copper) (rev 01)
>>> 07:00.0 RAID bus controller: Adaptec AAC-RAID (rev 09)
>>> 0b:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit
>>> Ethernet Controller (rev 06)
>>> 0b:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit
>>> Ethernet Controller (rev 06)
>>> 0c:05.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED
>>> Graphics Family
>>>
>>>
>>> dmesg:
>>> [    4.936885] e1000: Intel(R) PRO/1000 Network Driver - version
>>> 7.3.21-k8-NAPI
>>> [    4.936887] e1000: Copyright (c) 1999-2006 Intel Corporation.
>>> [    4.936966] e1000e: Intel(R) PRO/1000 Network Driver - 1.9.5-k
>>> [    4.936967] e1000e: Copyright(c) 1999 - 2012 Intel Corporation.
>>> [    4.938529] e1000e 0000:04:00.0: (unregistered net_device):
>>> Interrupt Throttling Rate (ints/sec) set to dynamic conservative 
>>> mode
>>> [    4.939598] e1000e 0000:04:00.0: irq 65 for MSI/MSI-X
>>> [    4.992246] e1000e 0000:04:00.0: eth0: (PCI 
>>> Express:2.5GT/s:Width
>>> x4) 00:1e:68:04:99:f8
>>> [    4.992657] e1000e 0000:04:00.0: eth0: Intel(R) PRO/1000 Network
>>> Connection
>>> [    4.992964] e1000e 0000:04:00.0: eth0: MAC: 5, PHY: 5, PBA No: 
>>> FFFFFF-0FF
>>> [    4.994745] e1000e 0000:04:00.1: (unregistered net_device):
>>> Interrupt Throttling Rate (ints/sec) set to dynamic conservative 
>>> mode
>>> [    4.996233] e1000e 0000:04:00.1: irq 66 for MSI/MSI-X
>>> [    5.050901] e1000e 0000:04:00.1: eth1: (PCI 
>>> Express:2.5GT/s:Width
>>> x4) 00:1e:68:04:99:f9
>>> [    5.051317] e1000e 0000:04:00.1: eth1: Intel(R) PRO/1000 Network
>>> Connection
>>> [    5.051623] e1000e 0000:04:00.1: eth1: MAC: 5, PHY: 5, PBA No: 
>>> FFFFFF-0FF
>>> [    5.051857] e1000e 0000:0b:00.0: Disabling ASPM  L1
>>> [    5.052168] e1000e 0000:0b:00.0: (unregistered net_device):
>>> Interrupt Throttling Rate (ints/sec) set to dynamic conservative 
>>> mode
>>> [    5.052611] e1000e 0000:0b:00.0: irq 67 for MSI/MSI-X
>>> [    5.223454] e1000e 0000:0b:00.0: eth2: (PCI 
>>> Express:2.5GT/s:Width
>>> x4) 00:1e:68:04:99:fa
>>> [    5.223864] e1000e 0000:0b:00.0: eth2: Intel(R) PRO/1000 Network
>>> Connection
>>> [    5.224178] e1000e 0000:0b:00.0: eth2: MAC: 0, PHY: 4, PBA No: 
>>> C83246-002
>>> [    5.224412] e1000e 0000:0b:00.1: Disabling ASPM  L1
>>> [    5.224709] e1000e 0000:0b:00.1: (unregistered net_device):
>>> Interrupt Throttling Rate (ints/sec) set to dynamic conservative 
>>> mode
>>> [    5.225168] e1000e 0000:0b:00.1: irq 68 for MSI/MSI-X
>>> [    5.397603] e1000e 0000:0b:00.1: eth3: (PCI 
>>> Express:2.5GT/s:Width
>>> x4) 00:1e:68:04:99:fb
>>> [    5.398021] e1000e 0000:0b:00.1: eth3: Intel(R) PRO/1000 Network
>>> Connection
>>> [    5.398336] e1000e 0000:0b:00.1: eth3: MAC: 0, PHY: 4, PBA No: 
>>> C83246-002
>>> [   13.859817] e1000e 0000:04:00.0: irq 65 for MSI/MSI-X
>>> [   13.962309] e1000e 0000:04:00.0: irq 65 for MSI/MSI-X
>>> [   17.150392] e1000e: eth0 NIC Link is Up 1000 Mbps Full Duplex,
>>> Flow Control: None
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe netdev" 
>>> in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>> ---
>> Network engineer
>> Denys Fedoryshchenko
>>
>> Dora Highway - Center Cebaco - 2nd Floor
>> Beirut, Lebanon
>> Tel:	+961 1 247373
>> E-Mail: denys@visp.net.lb
>> --
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> ---
> Network engineer
> Denys Fedoryshchenko
>
> Dora Highway - Center Cebaco - 2nd Floor
> Beirut, Lebanon
> Tel:	+961 1 247373
> E-Mail: denys@visp.net.lb
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

---
Network engineer
Denys Fedoryshchenko

Dora Highway - Center Cebaco - 2nd Floor
Beirut, Lebanon
Tel:	+961 1 247373
E-Mail: denys@visp.net.lb

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* e1000 rx emulation bug (Was: [PATCH] e1000: Reset rx ring index on receive overrun)
From: Samuel Thibault @ 2012-05-18 13:51 UTC (permalink / raw)
  To: Brandeburg, Jesse, qemu-devel, dlaor
  Cc: Jiri Pirko, e1000-devel@lists.sourceforge.net, Dean Nelson,
	Allan, Bruce W, linux-kernel@vger.kernel.org, David S. Miller,
	Ronciak, John, netdev@vger.kernel.org
In-Reply-To: <alpine.WNT.2.00.1205171718160.7900@jbrandeb-mobl2.amr.corp.intel.com>

Hello,

There seems to be a bug in qemu in the e1000 emulation, which triggers
an issue with the Linux driver.

What happens in Linux is the following:

- e1000_open 
  - e1000_configure
    - e1000_setup_rctl
      - enables E1000_RCTL_EN
    - e1000_configure_rx
      - sets RDT/RDH to 0
    - alloc_rx_buf
      - pushes buffers to the ring

with bad luck, or on high traffic of small packets, what is observed is
that between setting RDT/RDH and pushing buffers, the ring fills up in
qemu. Here is what happens there on the qemu side:

- e1000_receive
  - e1000_has_rxbufs
    - total_size <= s->rxbuf_size (because it's small)
      return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov;

although RDH == RDT == 0, it returns 1, because since RDT/RDH have
just been set to 0, set_rdt has cleared check_rxov. e1000_receive
thus believes there is room, and proceeds with filling the ring.
Unfortunately, since no buffer was pushed, desc.buffer_addr is NULL, and
thus the do loop skips all these nul rx descriptors of the ring, but
marking each of them with E1000_RXD_STAT_DD, and eventually wrapping
around.  From then on, since check_rxov has been set by the do loop,
nothing more is pushed, until the linux driver pushes buffers to the
ring. qemu can then fill some descriptors, and Linux read them, but
since the whole ring was filled with E1000_RXD_STAT_DD, Linux goes on
reading, and thus gets completely desynchronized with the device.

That raises two questions:

- what is the role of the check_rxov flag?  Is hardware really allowed
  to push in some cases, even when RDH==RDT?  Removing it makes things
  work just fine.
- BTW, when skipping a descriptor because of NULL address, does
  E1000_RXD_STAT_DD have to be set?

Samuel

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ 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