Netdev List
 help / color / mirror / Atom feed
* Re: [Announce] LARTC wiki available
From: John A. Sullivan III @ 2011-12-29 19:04 UTC (permalink / raw)
  To: Niccolò Belli
  Cc: netfilter, Linux Networking Developer Mailing List, lartc
In-Reply-To: <4EFC9FC2.1090503@linuxsystems.it>



----- Original Message -----
> From: "Niccolò Belli" <darkbasic@linuxsystems.it>
> To: lartc@vger.kernel.org
> Cc: netfilter@vger.kernel.org, "Linux Networking Developer Mailing List" <netdev@vger.kernel.org>
> Sent: Thursday, December 29, 2011 12:13:38 PM
> Subject: Re: [Announce] LARTC wiki available
> 
> Il 29/12/2011 17:19, Hagen Paul Pfeifer ha scritto:
> > But I don't like the idea to outhouse the existing wiki. Why two
> > wikis?
> 
> Because if you need an invite to edit something then it isn't a wiki
> anymore, for example.
> 
> 
> > What happened with the wiki server if you leave the university?
> 
> This isn't a problem, because relocating would be as simple as doing
> a
> database dump. Releasing dumps publicly wouldn't be a problem too.
> Also,
> there is no reason to keep using my servers when better alternatives
> arise. I created the wiki in a dedicated server because I didn't find
> viable alternatives (unlike for the mailing list) and considering the
> few feedbacks I received hopefully doing something tangible would
> create
> more interest: I'm pretty sure I'm not the only one who thinks there
> isn't enough documentation for the *end user*.
> 
> > So maybe the user
> > restriction on linuxfoundation.org should be changed?
> 
> Yes, IMHO.
> 
> > https://www.wiki.kernel.org/.
> 
> It seems a wiki for a kernel hacker, not for the end user.
> 
> P.S.
> Feedbacks are welcome, if there is no interest at all maybe we should
> just discard the idea after all.
> 
> <snip>
I can certainly concur that there is a lack of end user documentation.  I have found the net devs extremely helpful and am deeply grateful for their support but I do sometimes chuckle because the documentation and the responses are written from such a developer's context.  Of course, that is entirely expected and I don't mean the least bit of disrespect; I stand in complete awe of the net devs.

But the needs and perspectives of net devs and system engineers/admins are very different and rightly so.  So, I'd love to see a hybrid environment where we have the best of both worlds (but where sys admin types don't feel completely lost and overwhelmed).  Thanks, all - John

^ permalink raw reply

* Re: Allocation of MDIO bus numbers when fixed MDIO bus is enabled?
From: Anton Vorontsov @ 2011-12-29 19:10 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: afleming, netdev
In-Reply-To: <4EFC90C8.1060802@openwrt.org>

Hello,

On Thu, Dec 29, 2011 at 05:09:44PM +0100, Florian Fainelli wrote:
> An user of the r6040 driver has enabled support for the Fixed MDIO
> bus, so when the r6040 registers with its first instance, it will
> also try to register a MDIO bus with id 0, and this fails.
> 
> What's the proper solution to fixing this kind of issue? The same
> user proposed to use the pci slot and function as an id for
> registering the MDIO bus, which will work for PCI devices, but not
> for platform_devices for instance.

AFAIR, MDIO bus id doesn't have to be numeric, so you can change it
to parent's dev_name(). I.e. something like

 snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "%s-mdio", dev_name(dev));

So, the resulting PHYs would have IDs something like "dev-mdio:1".

Thanks,

-- 
Anton Vorontsov
Email: cbouatmailru@gmail.com

^ permalink raw reply

* Re: [PATCH] virtio_net: set/cancel work on ndo_open/ndo_stop
From: David Miller @ 2011-12-29 19:38 UTC (permalink / raw)
  To: rusty; +Cc: netdev, mst
In-Reply-To: <87pqf7fyld.fsf@rustcorp.com.au>


Michael will you integrate these patches from Rusty and submit them
to me along with other stuff you might have?

Or would you like me to apply them to net-next directly?

Thanks.

^ permalink raw reply

* Re: linux-next: Tree for Dec 28 (nfnetlink)
From: David Miller @ 2011-12-29 19:39 UTC (permalink / raw)
  To: rdunlap; +Cc: pablo, sfr, linux-next, linux-kernel, netdev, netfilter-devel
In-Reply-To: <4EFCB70C.50409@xenotime.net>

From: Randy Dunlap <rdunlap@xenotime.net>
Date: Thu, 29 Dec 2011 10:53:00 -0800

> On 12/28/2011 05:03 PM, Pablo Neira Ayuso wrote:
>> On Wed, Dec 28, 2011 at 03:33:04PM -0500, David Miller wrote:
>>> From: Randy Dunlap <rdunlap@xenotime.net>
>>> Date: Wed, 28 Dec 2011 13:19:08 -0800
>>>
>>>> On 12/28/2011 01:18 AM, Stephen Rothwell wrote:
>>>>> Hi all,
>>>>>
>>>>> I got bored :-(  I also hate tree wide, flag day changes :-(
>>>>>
>>>>> Changes since 20111222:
>>>>
>>>>
>>>>
>>>> warning: (NETFILTER_XT_MATCH_NFACCT) selects NETFILTER_NETLINK_ACCT which has unmet direct dependencies (NET && INET && NETFILTER && NETFILTER_ADVANCED)
>>>>
>>>> and then
>>>>
>>>> ERROR: "nfnetlink_subsys_unregister" [net/netfilter/nfnetlink_acct.ko] undefined!
>>>> ERROR: "nfnetlink_subsys_register" [net/netfilter/nfnetlink_acct.ko] undefined!
>>>>
>>>>
>>>> Full randconfig file is attached.
>>>
>>> Pablo please fix this, thanks.
>> 
>> Please, apply the following patch.
> 
> Acked-by: Randy Dunlap <rdunlap@xenotime.net>

Applied, thanks everyone.

^ permalink raw reply

* Re: [PATCH 1/5] sock_diag: Introduce the meminfo nla core
From: David Miller @ 2011-12-29 20:05 UTC (permalink / raw)
  To: xemul; +Cc: netdev
In-Reply-To: <4EFC754D.6000803@parallels.com>

From: Pavel Emelyanov <xemul@parallels.com>
Date: Thu, 29 Dec 2011 18:12:29 +0400

> Add a routine that dumps memory-related values of a socket.
> It's made as an array to make it possible to add more stuff
> here later without breaking compatibility.
> 
> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

If userspace is going to need to use the SK_MEMINFO_* values, then you
need to arrange linux/sock_diag.h such that it is exportable to
userspace, and all the kernel private non-userspace exported
components are properly __KERNEL__ ifdef protected.

^ permalink raw reply

* Re: [PATCH net-next] sch_tbf: report backlog information
From: David Miller @ 2011-12-29 20:07 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1325150864.2607.37.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 29 Dec 2011 10:27:44 +0100

> Provide child qdisc backlog (byte count) information so that "tc -s
> qdisc" can report it to user.
> 
> qdisc netem 30: root refcnt 18 limit 1000 delay 20.0ms  10.0ms
>  Sent 948517 bytes 898 pkt (dropped 0, overlimits 0 requeues 1) 
>  rate 175056bit 16pps backlog 114b 1p requeues 1 
> qdisc tbf 40: parent 30: rate 256000bit burst 20Kb/8 mpu 0b lat 0us 
>  Sent 948517 bytes 898 pkt (dropped 15, overlimits 611 requeues 0) 
>  backlog 18168b 12p requeues 0 
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH net-next 1/2] mlx4_core: using array index for sense_allowed
From: David Miller @ 2011-12-29 20:08 UTC (permalink / raw)
  To: yevgenyp; +Cc: netdev
In-Reply-To: <4EFCA68A.4010207@mellanox.co.il>

From: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Date: Thu, 29 Dec 2011 19:42:34 +0200

> 
> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>

Applied.

^ permalink raw reply

* Re: [PATCH net-next 2/2] mlx4_core: limiting VF port options
From: David Miller @ 2011-12-29 20:09 UTC (permalink / raw)
  To: yevgenyp; +Cc: netdev
In-Reply-To: <4EFCA68F.9060904@mellanox.co.il>

From: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Date: Thu, 29 Dec 2011 19:42:39 +0200

> 
> At the moment VFs can only operate in Eth mode.
> In addition we don't want the VF to attempt link sensing,
> so we block this option as well.
> 
> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>

Applied, but:

> +#define MLX4_VF_PORT_ETH_ONLY_MASK	0xE6

Why don't you just clearly define what all the port type bits mean
instead of only defining some arbitrary combination of them?

What if people want to experiment with other bit mask settings?  They
can't do that if you don't document the layout fully and properly.

^ permalink raw reply

* [PATCH] ipv6: Report TCP timetstamp info in cacheinfo just like ipv4 does.
From: David Miller @ 2011-12-29 20:23 UTC (permalink / raw)
  To: netdev


I missed this while adding ipv6 support to inet_peer.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv6/route.c |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0940729..30de9e7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2360,11 +2360,13 @@ static int rt6_fill_node(struct net *net,
 			 int iif, int type, u32 pid, u32 seq,
 			 int prefix, int nowait, unsigned int flags)
 {
+	const struct inet_peer *peer;
 	struct rtmsg *rtm;
 	struct nlmsghdr *nlh;
 	long expires;
 	u32 table;
 	struct neighbour *n;
+	u32 ts, tsage;
 
 	if (prefix) {	/* user wants prefix routes only */
 		if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
@@ -2471,7 +2473,14 @@ static int rt6_fill_node(struct net *net,
 	else
 		expires = INT_MAX;
 
-	if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0,
+	peer = rt->rt6i_peer;
+	ts = tsage = 0;
+	if (peer && peer->tcp_ts_stamp) {
+		ts = peer->tcp_ts;
+		tsage = get_seconds() - peer->tcp_ts_stamp;
+	}
+
+	if (rtnl_put_cacheinfo(skb, &rt->dst, 0, ts, tsage,
 			       expires, rt->dst.error) < 0)
 		goto nla_put_failure;
 
-- 
1.7.7.4

^ permalink raw reply related

* Re: [PATCH] virtio_net: set/cancel work on ndo_open/ndo_stop
From: Michael S. Tsirkin @ 2011-12-29 20:31 UTC (permalink / raw)
  To: David Miller; +Cc: rusty, netdev
In-Reply-To: <20111229.143806.1923729018497055525.davem@davemloft.net>

On Thu, Dec 29, 2011 at 02:38:06PM -0500, David Miller wrote:
> 
> Michael will you integrate these patches from Rusty and submit them
> to me along with other stuff you might have?
> 
> Or would you like me to apply them to net-next directly?
> 
> Thanks.

For personal reasons, my availability in this merge cycle is limited, so
net-next directly's better.

Thanks,

-- 
MST

^ permalink raw reply

* Re: [PATCH] virtio_net: set/cancel work on ndo_open/ndo_stop
From: Michael S. Tsirkin @ 2011-12-29 20:33 UTC (permalink / raw)
  To: Rusty Russell; +Cc: netdev
In-Reply-To: <87hb0kgiwn.fsf@rustcorp.com.au>

On Thu, Dec 29, 2011 at 01:53:52PM +1030, Rusty Russell wrote:
> Michael S. Tsirkin noticed that we could run the refill work after
> ndo_close, which can re-enable napi - we don't disable it until
> virtnet_remove.  This is clearly wrong, so move the workqueue control
> to ndo_open and ndo_stop (aka. virtnet_open and virtnet_close).
> 
> One subtle point: virtnet_probe() could simply fail if it couldn't
> allocate a receive buffer, but that's less polite in virtnet_open() so
> we schedule a refill as we do in the normal receive path if we run out
> of memory.
> 
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  drivers/net/virtio_net.c |   17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -439,7 +439,13 @@ static int add_recvbuf_mergeable(struct 
>  	return err;
>  }
>  
> -/* Returns false if we couldn't fill entirely (OOM). */
> +/*
> + * Returns false if we couldn't fill entirely (OOM).
> + *
> + * Normally run in the receive path, but can also be run from ndo_open
> + * before we're receiving packets, or from refill_work which is
> + * careful to disable receiving (using napi_disable).
> + */
>  static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
>  {
>  	int err;
> @@ -719,6 +725,10 @@ static int virtnet_open(struct net_devic
>  {
>  	struct virtnet_info *vi = netdev_priv(dev);
>  
> +	/* Make sure we have some buffers: if oom use wq. */
> +	if (!try_fill_recv(vi, GFP_KERNEL))
> +		schedule_delayed_work(&vi->refill, 0);
> +
>  	virtnet_napi_enable(vi);
>  	return 0;
>  }
> @@ -772,6 +782,8 @@ static int virtnet_close(struct net_devi
>  {
>  	struct virtnet_info *vi = netdev_priv(dev);
>  
> +	/* Make sure refill_work doesn't re-enable napi! */
> +	cancel_delayed_work_sync(&vi->refill);
>  	napi_disable(&vi->napi);
>  
>  	return 0;
> @@ -1082,7 +1094,6 @@ static int virtnet_probe(struct virtio_d
>  
>  unregister:
>  	unregister_netdev(dev);
> -	cancel_delayed_work_sync(&vi->refill);
>  free_vqs:
>  	vdev->config->del_vqs(vdev);
>  free_stats:
> @@ -1121,9 +1132,7 @@ static void __devexit virtnet_remove(str
>  	/* Stop all the virtqueues. */
>  	vdev->config->reset(vdev);
>  
> -
>  	unregister_netdev(vi->dev);
> -	cancel_delayed_work_sync(&vi->refill);
>  
>  	/* Free unused buffers in both send and recv, if any. */
>  	free_unused_bufs(vi);

^ permalink raw reply

* Re: [PATCH] virtio_net: use non-reentrant workqueue.
From: Michael S. Tsirkin @ 2011-12-29 20:33 UTC (permalink / raw)
  To: Rusty Russell; +Cc: netdev, Tejun Heo
In-Reply-To: <87ehvogitg.fsf@rustcorp.com.au>

On Thu, Dec 29, 2011 at 01:55:47PM +1030, Rusty Russell wrote:
> Michael S. Tsirkin also noticed that we could run the refill work
> multiple CPUs: if we kick off a refill on one CPU and then on another,
> they would both manipulate the queue at the same time (they use
> napi_disable to avoid racing against the receive handler itself).
> 
> Tejun points out that this is what the WQ_NON_REENTRANT flag is for,
> and that there is a convenient system kthread we can use.
> 
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  drivers/net/virtio_net.c |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -507,7 +507,7 @@ static void refill_work(struct work_stru
>  	/* In theory, this can happen: if we don't get any buffers in
>  	 * we will *never* try to fill again. */
>  	if (still_empty)
> -		schedule_delayed_work(&vi->refill, HZ/2);
> +		queue_delayed_work(system_nrt_wq, &vi->refill, HZ/2);
>  }
>  
>  static int virtnet_poll(struct napi_struct *napi, int budget)
> @@ -526,7 +526,7 @@ again:
>  
>  	if (vi->num < vi->max / 2) {
>  		if (!try_fill_recv(vi, GFP_ATOMIC))
> -			schedule_delayed_work(&vi->refill, 0);
> +			queue_delayed_work(system_nrt_wq, &vi->refill, 0);
>  	}
>  
>  	/* Out of packets? */
> @@ -727,7 +727,7 @@ static int virtnet_open(struct net_devic
>  
>  	/* Make sure we have some buffers: if oom use wq. */
>  	if (!try_fill_recv(vi, GFP_KERNEL))
> -		schedule_delayed_work(&vi->refill, 0);
> +		queue_delayed_work(system_nrt_wq, &vi->refill, 0);
>  
>  	virtnet_napi_enable(vi);
>  	return 0;

^ permalink raw reply

* Re: [PATCH] virtio_net: set/cancel work on ndo_open/ndo_stop
From: David Miller @ 2011-12-29 21:44 UTC (permalink / raw)
  To: mst; +Cc: rusty, netdev
In-Reply-To: <20111229203150.GA5015@redhat.com>

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Thu, 29 Dec 2011 22:31:50 +0200

> On Thu, Dec 29, 2011 at 02:38:06PM -0500, David Miller wrote:
>> 
>> Michael will you integrate these patches from Rusty and submit them
>> to me along with other stuff you might have?
>> 
>> Or would you like me to apply them to net-next directly?
>> 
>> Thanks.
> 
> For personal reasons, my availability in this merge cycle is limited, so
> net-next directly's better.

Ok.

^ permalink raw reply

* Re: [PATCH] virtio_net: set/cancel work on ndo_open/ndo_stop
From: David Miller @ 2011-12-29 21:44 UTC (permalink / raw)
  To: mst; +Cc: rusty, netdev
In-Reply-To: <20111229203302.GA5051@redhat.com>

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Thu, 29 Dec 2011 22:33:02 +0200

> On Thu, Dec 29, 2011 at 01:53:52PM +1030, Rusty Russell wrote:
>> Michael S. Tsirkin noticed that we could run the refill work after
>> ndo_close, which can re-enable napi - we don't disable it until
>> virtnet_remove.  This is clearly wrong, so move the workqueue control
>> to ndo_open and ndo_stop (aka. virtnet_open and virtnet_close).
>> 
>> One subtle point: virtnet_probe() could simply fail if it couldn't
>> allocate a receive buffer, but that's less polite in virtnet_open() so
>> we schedule a refill as we do in the normal receive path if we run out
>> of memory.
>> 
>> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> 
> Acked-by: Michael S. Tsirkin <mst@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH] virtio_net: use non-reentrant workqueue.
From: David Miller @ 2011-12-29 21:44 UTC (permalink / raw)
  To: mst; +Cc: rusty, netdev, tj
In-Reply-To: <20111229203314.GB5051@redhat.com>

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Thu, 29 Dec 2011 22:33:14 +0200

> On Thu, Dec 29, 2011 at 01:55:47PM +1030, Rusty Russell wrote:
>> Michael S. Tsirkin also noticed that we could run the refill work
>> multiple CPUs: if we kick off a refill on one CPU and then on another,
>> they would both manipulate the queue at the same time (they use
>> napi_disable to avoid racing against the receive handler itself).
>> 
>> Tejun points out that this is what the WQ_NON_REENTRANT flag is for,
>> and that there is a convenient system kthread we can use.
>> 
>> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> 
> Acked-by: Michael S. Tsirkin <mst@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Bjarke Istrup Pedersen @ 2011-12-29 22:00 UTC (permalink / raw)
  To: Francois Romieu
  Cc: David Miller, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20111229183902.GC21946@electric-eye.fr.zoreil.com>

2011/12/29 Francois Romieu <romieu@fr.zoreil.com>:
> Francois Romieu <romieu@fr.zoreil.com> :
> [...]
>> Feel free to try the extra "new year's eve week end is getting closer"
>> patch below (against net-next).
>>
>> You have been warned.
>
> The one below could be a bit better.
>
> Out for dinner.

Thanks, I'll try that one in a while, once I'm done bisecting 3.1.4 ->
3.1.5, since all kernels after 3.1.4 won't pass control onto init.

/Bjarke

> diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
> index 5c4983b..66e5c08 100644
> --- a/drivers/net/ethernet/via/via-rhine.c
> +++ b/drivers/net/ethernet/via/via-rhine.c
> @@ -42,7 +42,8 @@
>
>  #define DEBUG
>  static int debug = 1;  /* 1 normal messages, 0 quiet .. 7 verbose. */
> -static int max_interrupt_work = 20;
> +#define RHINE_MSG_DEFAULT \
> +        (NETIF_MSG_INTR)
>
>  /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
>    Setting to > 1518 effectively disables this feature. */
> @@ -128,11 +129,9 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
>  MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
>  MODULE_LICENSE("GPL");
>
> -module_param(max_interrupt_work, int, 0);
>  module_param(debug, int, 0);
>  module_param(rx_copybreak, int, 0);
>  module_param(avoid_D3, bool, 0);
> -MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
>  MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
>  MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
>  MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
> @@ -351,16 +350,25 @@ static const int mmio_verify_registers[] = {
>
>  /* Bits in the interrupt status/mask registers. */
>  enum intr_status_bits {
> -       IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
> -       IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210,
> -       IntrPCIErr=0x0040,
> -       IntrStatsMax=0x0080, IntrRxEarly=0x0100,
> -       IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
> -       IntrTxAborted=0x2000, IntrLinkChange=0x4000,
> -       IntrRxWakeUp=0x8000,
> -       IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
> -       IntrTxDescRace=0x080000,        /* mapped from IntrStatus2 */
> -       IntrTxErrSummary=0x082218,
> +       IntrRxDone      = 0x0001,
> +       IntrTxDone      = 0x0002,
> +       IntrRxErr       = 0x0004,
> +       IntrTxError     = 0x0008,
> +       IntrRxEmpty     = 0x0020,
> +       IntrPCIErr      = 0x0040,
> +       IntrStatsMax    = 0x0080,
> +       IntrRxEarly     = 0x0100,
> +       IntrTxUnderrun  = 0x0210,
> +       IntrRxOverflow  = 0x0400,
> +       IntrRxDropped   = 0x0800,
> +       IntrRxNoBuf     = 0x1000,
> +       IntrTxAborted   = 0x2000,
> +       IntrLinkChange  = 0x4000,
> +       IntrRxWakeUp    = 0x8000,
> +       IntrTxDescRace          = 0x080000,     /* mapped from IntrStatus2 */
> +       IntrNormalSummary       = IntrRxDone | IntrTxDone,
> +       IntrTxErrSummary        = IntrTxDescRace | IntrTxAborted | IntrTxError |
> +                                 IntrTxUnderrun,
>  };
>
>  /* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
> @@ -439,8 +447,12 @@ struct rhine_private {
>        struct net_device *dev;
>        struct napi_struct napi;
>        spinlock_t lock;
> +       struct mutex task_lock;
> +       struct work_struct slow_event_task;
>        struct work_struct reset_task;
>
> +       u32 msg_enable;
> +
>        /* Frequently used values: keep some adjacent for cache effect. */
>        u32 quirks;
>        struct rx_desc *rx_head_desc;
> @@ -482,7 +494,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
>  static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
>  static void rhine_tx(struct net_device *dev);
>  static int rhine_rx(struct net_device *dev, int limit);
> -static void rhine_error(struct net_device *dev, int intr_status);
>  static void rhine_set_rx_mode(struct net_device *dev);
>  static struct net_device_stats *rhine_get_stats(struct net_device *dev);
>  static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
> @@ -497,6 +508,8 @@ static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask);
>  static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask);
>  static void rhine_init_cam_filter(struct net_device *dev);
>  static void rhine_update_vcam(struct net_device *dev);
> +static void rhine_slow_event_task(struct work_struct *work);
> +static void rhine_restart_tx(struct net_device *dev);
>
>  #define RHINE_WAIT_FOR(condition)                              \
>  do {                                                           \
> @@ -508,7 +521,7 @@ do {                                                                \
>                        1024 - i, __func__, __LINE__);          \
>  } while (0)
>
> -static inline u32 get_intr_status(struct net_device *dev)
> +static u32 get_intr_status(struct net_device *dev)
>  {
>        struct rhine_private *rp = netdev_priv(dev);
>        void __iomem *ioaddr = rp->base;
> @@ -521,6 +534,16 @@ static inline u32 get_intr_status(struct net_device *dev)
>        return intr_status;
>  }
>
> +static void rhine_ack_event(struct rhine_private *rp, u32 mask)
> +{
> +       void __iomem *ioaddr = rp->base;
> +
> +       if (rp->quirks & rqStatusWBRace)
> +               iowrite8(mask >> 16, ioaddr + IntrStatus2);
> +       iowrite16(mask, ioaddr + IntrStatus);
> +       mmiowb();
> +}
> +
>  /*
>  * Get power related registers into sane state.
>  * Notify user about past WOL event.
> @@ -657,23 +680,127 @@ static void rhine_poll(struct net_device *dev)
>  }
>  #endif
>
> +static void rhine_kick_tx_threshold(struct rhine_private *rp)
> +{
> +       if (rp->tx_thresh < 0xe0) {
> +               void __iomem *ioaddr = rp->base;
> +
> +               rp->tx_thresh += 0x20;
> +               BYTE_REG_BITS_SET(rp->tx_thresh, 0x80, ioaddr + TxConfig);
> +       }
> +}
> +
> +static void rhine_tx_err(struct rhine_private *rp, u32 status)
> +{
> +       struct net_device *dev = rp->dev;
> +
> +       if (status & IntrTxAborted) {
> +               netif_info(rp, tx_err, dev,
> +                          "Abort %08x, frame dropped\n", status);
> +       }
> +
> +       if (status & IntrTxUnderrun) {
> +               rhine_kick_tx_threshold(rp);
> +               netif_info(rp, tx_err ,dev, "Transmitter underrun, "
> +                          "Tx threshold now %02x\n", rp->tx_thresh);
> +       }
> +
> +       if (status & IntrTxDescRace)
> +               netif_info(rp, tx_err, dev, "Tx descriptor write-back race\n");
> +
> +       if ((status & IntrTxError) &&
> +           (status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) == 0) {
> +               rhine_kick_tx_threshold(rp);
> +               netif_info(rp, tx_err, dev, "Unspecified error. "
> +                          "Tx threshold now %02x\n", rp->tx_thresh);
> +       }
> +
> +       rhine_restart_tx(dev);
> +}
> +
> +static void rhine_update_rx_crc_and_missed_errord(struct rhine_private *rp)
> +{
> +       void __iomem *ioaddr = rp->base;
> +       struct net_device_stats *stats = &rp->dev->stats;
> +
> +       stats->rx_crc_errors    += ioread16(ioaddr + RxCRCErrs);
> +       stats->rx_missed_errors += ioread16(ioaddr + RxMissed);
> +
> +       /*
> +        * Clears the "tally counters" for CRC errors and missed frames(?).
> +        * It has been reported that some chips need a write of 0 to clear
> +        * these, for others the counters are set to 1 when written to and
> +        * instead cleared when read. So we clear them both ways ...
> +        */
> +       iowrite32(0, ioaddr + RxMissed);
> +       ioread16(ioaddr + RxCRCErrs);
> +       ioread16(ioaddr + RxMissed);
> +}
> +
> +#define RHINE_EVENT_NAPI_RX    (IntrRxDone | \
> +                                IntrRxErr | \
> +                                IntrRxEmpty | \
> +                                IntrRxOverflow | \
> +                                IntrRxDropped | \
> +                                IntrRxNoBuf | \
> +                                IntrRxWakeUp)
> +
> +#define RHINE_EVENT_NAPI_TX_ERR        (IntrTxError | \
> +                                IntrTxAborted | \
> +                                IntrTxUnderrun | \
> +                                IntrTxDescRace)
> +#define RHINE_EVENT_NAPI_TX    (IntrTxDone | RHINE_EVENT_NAPI_TX_ERR)
> +
> +#define RHINE_EVENT_NAPI       (RHINE_EVENT_NAPI_RX | \
> +                                RHINE_EVENT_NAPI_TX | \
> +                                IntrStatsMax)
> +#define RHINE_EVENT_SLOW       (IntrPCIErr | IntrLinkChange)
> +#define RHINE_EVENT            (RHINE_EVENT_NAPI | RHINE_EVENT_SLOW)
> +
>  static int rhine_napipoll(struct napi_struct *napi, int budget)
>  {
>        struct rhine_private *rp = container_of(napi, struct rhine_private, napi);
>        struct net_device *dev = rp->dev;
>        void __iomem *ioaddr = rp->base;
> -       int work_done;
> +       u16 enable_mask = RHINE_EVENT & 0xffff;
> +       int work_done = 0;
> +       u32 status;
> +
> +       status = get_intr_status(dev);
> +       rhine_ack_event(rp, status & ~RHINE_EVENT_SLOW);
> +
> +       if (status & RHINE_EVENT_NAPI_RX)
> +               work_done += rhine_rx(dev, budget);
> +
> +       if (status & RHINE_EVENT_NAPI_TX) {
> +               if (status & RHINE_EVENT_NAPI_TX_ERR) {
> +                       /* Avoid scavenging before Tx engine turned off */
> +                       RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd) & CmdTxOn));
> +                       if (ioread8(ioaddr + ChipCmd) & CmdTxOn)
> +                               netif_warn(rp, tx_err, dev, "Tx still on\n");
> +               }
>
> -       work_done = rhine_rx(dev, budget);
> +               rhine_tx(dev);
> +
> +               if (status & RHINE_EVENT_NAPI_TX_ERR)
> +                       rhine_tx_err(rp, status);
> +       }
> +
> +       if (status & IntrStatsMax) {
> +               spin_lock(&rp->lock);
> +               rhine_update_rx_crc_and_missed_errord(rp);
> +               spin_unlock(&rp->lock);
> +       }
> +
> +       if (status & RHINE_EVENT_SLOW) {
> +               enable_mask &= ~RHINE_EVENT_SLOW;
> +               schedule_work(&rp->slow_event_task);
> +       }
>
>        if (work_done < budget) {
>                napi_complete(napi);
> -
> -               iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
> -                         IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
> -                         IntrTxDone | IntrTxError | IntrTxUnderrun |
> -                         IntrPCIErr | IntrStatsMax | IntrLinkChange,
> -                         ioaddr + IntrEnable);
> +               iowrite16(enable_mask, ioaddr + IntrEnable);
> +               mmiowb();
>        }
>        return work_done;
>  }
> @@ -797,6 +924,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
>        rp->quirks = quirks;
>        rp->pioaddr = pioaddr;
>        rp->pdev = pdev;
> +       rp->msg_enable = netif_msg_init(-1, RHINE_MSG_DEFAULT);
>
>        rc = pci_request_regions(pdev, DRV_NAME);
>        if (rc)
> @@ -856,7 +984,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
>        dev->irq = pdev->irq;
>
>        spin_lock_init(&rp->lock);
> +       mutex_init(&rp->task_lock);
>        INIT_WORK(&rp->reset_task, rhine_reset_task);
> +       INIT_WORK(&rp->slow_event_task, rhine_slow_event_task);
>
>        rp->mii_if.dev = dev;
>        rp->mii_if.mdio_read = mdio_read;
> @@ -1310,12 +1440,7 @@ static void init_registers(struct net_device *dev)
>
>        napi_enable(&rp->napi);
>
> -       /* Enable interrupts by setting the interrupt mask. */
> -       iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
> -              IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
> -              IntrTxDone | IntrTxError | IntrTxUnderrun |
> -              IntrPCIErr | IntrStatsMax | IntrLinkChange,
> -              ioaddr + IntrEnable);
> +       iowrite16(RHINE_EVENT & 0xffff, ioaddr + IntrEnable);
>
>        iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
>               ioaddr + ChipCmd);
> @@ -1434,13 +1559,10 @@ static void rhine_reset_task(struct work_struct *work)
>                                                reset_task);
>        struct net_device *dev = rp->dev;
>
> -       /* protect against concurrent rx interrupts */
> -       disable_irq(rp->pdev->irq);
> +       mutex_lock(&rp->task_lock);
>
>        napi_disable(&rp->napi);
>
> -       spin_lock_bh(&rp->lock);
> -
>        /* clear all descriptors */
>        free_tbufs(dev);
>        free_rbufs(dev);
> @@ -1451,12 +1573,11 @@ static void rhine_reset_task(struct work_struct *work)
>        rhine_chip_reset(dev);
>        init_registers(dev);
>
> -       spin_unlock_bh(&rp->lock);
> -       enable_irq(rp->pdev->irq);
> -
>        dev->trans_start = jiffies; /* prevent tx timeout */
>        dev->stats.tx_errors++;
>        netif_wake_queue(dev);
> +
> +       mutex_unlock(&rp->task_lock);
>  }
>
>  static void rhine_tx_timeout(struct net_device *dev)
> @@ -1477,7 +1598,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
>        struct rhine_private *rp = netdev_priv(dev);
>        void __iomem *ioaddr = rp->base;
>        unsigned entry;
> -       unsigned long flags;
>
>        /* Caution: the write order is important here, set the field
>           with the "ownership" bits last. */
> @@ -1529,7 +1649,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
>                rp->tx_ring[entry].tx_status = 0;
>
>        /* lock eth irq */
> -       spin_lock_irqsave(&rp->lock, flags);
>        wmb();
>        rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn);
>        wmb();
> @@ -1543,15 +1662,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
>                BYTE_REG_BITS_ON(1 << 7, ioaddr + TQWake);
>
>        /* Wake the potentially-idle transmit channel */
> -       iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
> -              ioaddr + ChipCmd1);
> +       iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand, ioaddr + ChipCmd1);
>        IOSYNC;
>
>        if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN)
>                netif_stop_queue(dev);
>
> -       spin_unlock_irqrestore(&rp->lock, flags);
> -
>        if (debug > 4) {
>                netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n",
>                           rp->cur_tx-1, entry);
> @@ -1565,63 +1681,26 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
>  {
>        struct net_device *dev = dev_instance;
>        struct rhine_private *rp = netdev_priv(dev);
> -       void __iomem *ioaddr = rp->base;
> -       u32 intr_status;
> -       int boguscnt = max_interrupt_work;
> +       u32 status;
>        int handled = 0;
>
> -       while ((intr_status = get_intr_status(dev))) {
> -               handled = 1;
> -
> -               /* Acknowledge all of the current interrupt sources ASAP. */
> -               if (intr_status & IntrTxDescRace)
> -                       iowrite8(0x08, ioaddr + IntrStatus2);
> -               iowrite16(intr_status & 0xffff, ioaddr + IntrStatus);
> -               IOSYNC;
> -
> -               if (debug > 4)
> -                       netdev_dbg(dev, "Interrupt, status %08x\n",
> -                                  intr_status);
> -
> -               if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
> -                                  IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
> -                       iowrite16(IntrTxAborted |
> -                                 IntrTxDone | IntrTxError | IntrTxUnderrun |
> -                                 IntrPCIErr | IntrStatsMax | IntrLinkChange,
> -                                 ioaddr + IntrEnable);
> +       status = get_intr_status(dev);
>
> -                       napi_schedule(&rp->napi);
> -               }
> +       netif_dbg(rp, intr, dev, "Interrupt, status %08x\n", status);
>
> -               if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
> -                       if (intr_status & IntrTxErrSummary) {
> -                               /* Avoid scavenging before Tx engine turned off */
> -                               RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
> -                               if (debug > 2 &&
> -                                   ioread8(ioaddr+ChipCmd) & CmdTxOn)
> -                                       netdev_warn(dev,
> -                                                   "%s: Tx engine still on\n",
> -                                                   __func__);
> -                       }
> -                       rhine_tx(dev);
> -               }
> +       if (status & RHINE_EVENT) {
> +               handled = 1;
>
> -               /* Abnormal error summary/uncommon events handlers. */
> -               if (intr_status & (IntrPCIErr | IntrLinkChange |
> -                                  IntrStatsMax | IntrTxError | IntrTxAborted |
> -                                  IntrTxUnderrun | IntrTxDescRace))
> -                       rhine_error(dev, intr_status);
> +               iowrite16(0x0000, rp->base + IntrEnable);
> +               mmiowb();
> +               napi_schedule(&rp->napi);
> +       }
>
> -               if (--boguscnt < 0) {
> -                       netdev_warn(dev, "Too much work at interrupt, status=%#08x\n",
> -                                   intr_status);
> -                       break;
> -               }
> +       if (status & ~(IntrLinkChange | IntrStatsMax | RHINE_EVENT_NAPI)) {
> +               netif_err(rp, intr, dev, "Something Wicked happened! %08x\n",
> +                         status);
>        }
>
> -       if (debug > 3)
> -               netdev_dbg(dev, "exiting interrupt, status=%08x\n",
> -                          ioread16(ioaddr + IntrStatus));
>        return IRQ_RETVAL(handled);
>  }
>
> @@ -1632,8 +1711,6 @@ static void rhine_tx(struct net_device *dev)
>        struct rhine_private *rp = netdev_priv(dev);
>        int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
>
> -       spin_lock(&rp->lock);
> -
>        /* find and cleanup dirty tx descriptors */
>        while (rp->dirty_tx != rp->cur_tx) {
>                txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
> @@ -1687,8 +1764,6 @@ static void rhine_tx(struct net_device *dev)
>        }
>        if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
>                netif_wake_queue(dev);
> -
> -       spin_unlock(&rp->lock);
>  }
>
>  /**
> @@ -1839,20 +1914,8 @@ static int rhine_rx(struct net_device *dev, int limit)
>        return count;
>  }
>
> -/*
> - * Clears the "tally counters" for CRC errors and missed frames(?).
> - * It has been reported that some chips need a write of 0 to clear
> - * these, for others the counters are set to 1 when written to and
> - * instead cleared when read. So we clear them both ways ...
> - */
> -static inline void clear_tally_counters(void __iomem *ioaddr)
> +static void rhine_restart_tx(struct net_device *dev)
>  {
> -       iowrite32(0, ioaddr + RxMissed);
> -       ioread16(ioaddr + RxCRCErrs);
> -       ioread16(ioaddr + RxMissed);
> -}
> -
> -static void rhine_restart_tx(struct net_device *dev) {
>        struct rhine_private *rp = netdev_priv(dev);
>        void __iomem *ioaddr = rp->base;
>        int entry = rp->dirty_tx % TX_RING_SIZE;
> @@ -1880,8 +1943,7 @@ static void rhine_restart_tx(struct net_device *dev) {
>                iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
>                       ioaddr + ChipCmd1);
>                IOSYNC;
> -       }
> -       else {
> +       } else {
>                /* This should never happen */
>                if (debug > 1)
>                        netdev_warn(dev, "%s() Another error occurred %08x\n",
> @@ -1890,72 +1952,46 @@ static void rhine_restart_tx(struct net_device *dev) {
>
>  }
>
> -static void rhine_error(struct net_device *dev, int intr_status)
> +static void rhine_slow_event_task(struct work_struct *work)
>  {
> -       struct rhine_private *rp = netdev_priv(dev);
> +       struct rhine_private *rp =
> +               container_of(work, struct rhine_private, slow_event_task);
> +       struct net_device *dev = rp->dev;
>        void __iomem *ioaddr = rp->base;
> +       u32 intr_status;
>
> -       spin_lock(&rp->lock);
> +       if (!netif_running(dev))
> +               return;
> +
> +       mutex_lock(&rp->task_lock);
> +
> +       intr_status = get_intr_status(dev);
> +       rhine_ack_event(rp, intr_status & RHINE_EVENT_SLOW);
>
>        if (intr_status & IntrLinkChange)
>                rhine_check_media(dev, 0);
> -       if (intr_status & IntrStatsMax) {
> -               dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
> -               dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
> -               clear_tally_counters(ioaddr);
> -       }
> -       if (intr_status & IntrTxAborted) {
> -               if (debug > 1)
> -                       netdev_info(dev, "Abort %08x, frame dropped\n",
> -                                   intr_status);
> -       }
> -       if (intr_status & IntrTxUnderrun) {
> -               if (rp->tx_thresh < 0xE0)
> -                       BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
> -               if (debug > 1)
> -                       netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n",
> -                                   rp->tx_thresh);
> -       }
> -       if (intr_status & IntrTxDescRace) {
> -               if (debug > 2)
> -                       netdev_info(dev, "Tx descriptor write-back race\n");
> -       }
> -       if ((intr_status & IntrTxError) &&
> -           (intr_status & (IntrTxAborted |
> -            IntrTxUnderrun | IntrTxDescRace)) == 0) {
> -               if (rp->tx_thresh < 0xE0) {
> -                       BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
> -               }
> -               if (debug > 1)
> -                       netdev_info(dev, "Unspecified error. Tx threshold now %02x\n",
> -                                   rp->tx_thresh);
> -       }
> -       if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace |
> -                          IntrTxError))
> -               rhine_restart_tx(dev);
>
> -       if (intr_status & ~(IntrLinkChange | IntrStatsMax | IntrTxUnderrun |
> -                           IntrTxError | IntrTxAborted | IntrNormalSummary |
> -                           IntrTxDescRace)) {
> -               if (debug > 1)
> -                       netdev_err(dev, "Something Wicked happened! %08x\n",
> -                                  intr_status);
> -       }
> +       /* FIXME: ignore ? */
> +       if (intr_status & IntrPCIErr)
> +               netif_warn(rp, hw, dev, "PCI error\n");
>
> -       spin_unlock(&rp->lock);
> +       napi_disable(&rp->napi);
> +       iowrite16(0x0000, ioaddr + IntrEnable);
> +       mmiowb();
> +       /* Slow and safe. Consider __napi_schedule as a replacement ? */
> +       napi_enable(&rp->napi);
> +       napi_schedule(&rp->napi);
> +
> +       mutex_unlock(&rp->task_lock);
>  }
>
>  static struct net_device_stats *rhine_get_stats(struct net_device *dev)
>  {
>        struct rhine_private *rp = netdev_priv(dev);
> -       void __iomem *ioaddr = rp->base;
> -       unsigned long flags;
>
> -       spin_lock_irqsave(&rp->lock, flags);
> -       dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
> -       dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
> -       clear_tally_counters(ioaddr);
> -       spin_unlock_irqrestore(&rp->lock, flags);
> +       spin_lock_bh(&rp->lock);
> +       rhine_update_rx_crc_and_missed_errord(rp);
> +       spin_unlock_bh(&rp->lock);
>
>        return &dev->stats;
>  }
> @@ -2022,9 +2058,9 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
>        struct rhine_private *rp = netdev_priv(dev);
>        int rc;
>
> -       spin_lock_irq(&rp->lock);
> +       mutex_lock(&rp->task_lock);
>        rc = mii_ethtool_gset(&rp->mii_if, cmd);
> -       spin_unlock_irq(&rp->lock);
> +       mutex_unlock(&rp->task_lock);
>
>        return rc;
>  }
> @@ -2034,10 +2070,10 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
>        struct rhine_private *rp = netdev_priv(dev);
>        int rc;
>
> -       spin_lock_irq(&rp->lock);
> +       mutex_lock(&rp->task_lock);
>        rc = mii_ethtool_sset(&rp->mii_if, cmd);
> -       spin_unlock_irq(&rp->lock);
>        rhine_set_carrier(&rp->mii_if);
> +       mutex_unlock(&rp->task_lock);
>
>        return rc;
>  }
> @@ -2073,6 +2109,7 @@ static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
>        if (!(rp->quirks & rqWOL))
>                return;
>
> +       /* FIXME: huh ? */
>        spin_lock_irq(&rp->lock);
>        wol->supported = WAKE_PHY | WAKE_MAGIC |
>                         WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;  /* Untested */
> @@ -2092,6 +2129,7 @@ static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
>        if (wol->wolopts & ~support)
>                return -EINVAL;
>
> +       /* FIXME: huh (sic) ? */
>        spin_lock_irq(&rp->lock);
>        rp->wolopts = wol->wolopts;
>        spin_unlock_irq(&rp->lock);
> @@ -2119,10 +2157,10 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
>        if (!netif_running(dev))
>                return -EINVAL;
>
> -       spin_lock_irq(&rp->lock);
> +       mutex_lock(&rp->task_lock);
>        rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
> -       spin_unlock_irq(&rp->lock);
>        rhine_set_carrier(&rp->mii_if);
> +       mutex_unlock(&rp->task_lock);
>
>        return rc;
>  }
> @@ -2133,11 +2171,10 @@ static int rhine_close(struct net_device *dev)
>        void __iomem *ioaddr = rp->base;
>
>        napi_disable(&rp->napi);
> +       cancel_work_sync(&rp->slow_event_task);
>        cancel_work_sync(&rp->reset_task);
>        netif_stop_queue(dev);
>
> -       spin_lock_irq(&rp->lock);
> -
>        if (debug > 1)
>                netdev_dbg(dev, "Shutting down ethercard, status was %04x\n",
>                           ioread16(ioaddr + ChipCmd));
> @@ -2151,8 +2188,6 @@ static int rhine_close(struct net_device *dev)
>        /* Stop the chip's Tx and Rx processes. */
>        iowrite16(CmdStop, ioaddr + ChipCmd);
>
> -       spin_unlock_irq(&rp->lock);
> -
>        free_irq(rp->pdev->irq, dev);
>        free_rbufs(dev);
>        free_tbufs(dev);
> @@ -2239,10 +2274,12 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
>        netif_device_detach(dev);
>        pci_save_state(pdev);
>
> +       /* FIXME: ? */
>        spin_lock_irqsave(&rp->lock, flags);
>        rhine_shutdown(pdev);
>        spin_unlock_irqrestore(&rp->lock, flags);
>
> +       /* FIXME: nuclear workaround ? Check the commit log. */
>        free_irq(dev->irq, dev);
>        return 0;
>  }
> @@ -2257,6 +2294,7 @@ static int rhine_resume(struct pci_dev *pdev)
>        if (!netif_running(dev))
>                return 0;
>
> +       /* FIXME: see above. */
>        if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev))
>                netdev_err(dev, "request_irq failed\n");
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: David Miller @ 2011-12-29 22:05 UTC (permalink / raw)
  To: romieu; +Cc: gurligebis, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20111229183902.GC21946@electric-eye.fr.zoreil.com>

From: Francois Romieu <romieu@fr.zoreil.com>
Date: Thu, 29 Dec 2011 19:39:02 +0100

> Francois Romieu <romieu@fr.zoreil.com> :
> [...]
>> Feel free to try the extra "new year's eve week end is getting closer"
>> patch below (against net-next).
>> 
>> You have been warned.
> 
> The one below could be a bit better.

Obviously you'll need to resolve the use of rp->lock as an IRQ safe lock
in {get,src}_wol() so that this lock is consistently used as a BH safe
lock.  Your "Huh?" comments make it clear you are aware of this TODO. :-)

But other than that this patch looks good to me, just some testing and
debugging are needed.

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Bjarke Istrup Pedersen @ 2011-12-29 23:19 UTC (permalink / raw)
  To: David Miller; +Cc: romieu, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20111229.170514.1766899380937848638.davem@davemloft.net>

2011/12/29 David Miller <davem@davemloft.net>:
> From: Francois Romieu <romieu@fr.zoreil.com>
> Date: Thu, 29 Dec 2011 19:39:02 +0100
>
>> Francois Romieu <romieu@fr.zoreil.com> :
>> [...]
>>> Feel free to try the extra "new year's eve week end is getting closer"
>>> patch below (against net-next).
>>>
>>> You have been warned.
>>
>> The one below could be a bit better.
>
> Obviously you'll need to resolve the use of rp->lock as an IRQ safe lock
> in {get,src}_wol() so that this lock is consistently used as a BH safe
> lock.  Your "Huh?" comments make it clear you are aware of this TODO. :-)
>
> But other than that this patch looks good to me, just some testing and
> debugging are needed.

I got it to boot, had to revert another patch introduced in 3.1.5
that's causing alot of people problems, but thats another talk :)

It boots fine, untill it tries to bring up an interface, which causes
it to fails with a kernel panic.
Here is the output of the panic:
http://dev.gentoo.org/~gurligebis/kernel/panic.txt

/Bjarke

> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Bjarke Istrup Pedersen @ 2011-12-29 23:37 UTC (permalink / raw)
  To: David Miller; +Cc: romieu, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <CACPM=kV8NwYLAdODQHxYmJ21X0RmZ8KJT9szKdY2xa-DsesvQg@mail.gmail.com>

2011/12/30 Bjarke Istrup Pedersen <gurligebis@gentoo.org>:
> 2011/12/29 David Miller <davem@davemloft.net>:
>> From: Francois Romieu <romieu@fr.zoreil.com>
>> Date: Thu, 29 Dec 2011 19:39:02 +0100
>>
>>> Francois Romieu <romieu@fr.zoreil.com> :
>>> [...]
>>>> Feel free to try the extra "new year's eve week end is getting closer"
>>>> patch below (against net-next).
>>>>
>>>> You have been warned.
>>>
>>> The one below could be a bit better.
>>
>> Obviously you'll need to resolve the use of rp->lock as an IRQ safe lock
>> in {get,src}_wol() so that this lock is consistently used as a BH safe
>> lock.  Your "Huh?" comments make it clear you are aware of this TODO. :-)
>>
>> But other than that this patch looks good to me, just some testing and
>> debugging are needed.
>
> I got it to boot, had to revert another patch introduced in 3.1.5
> that's causing alot of people problems, but thats another talk :)
>
> It boots fine, untill it tries to bring up an interface, which causes
> it to fails with a kernel panic.
> Here is the output of the panic:
> http://dev.gentoo.org/~gurligebis/kernel/panic.txt
>
> /Bjarke

Hmm, it seems like this problem isn't related to the driver, but
related to the current HEAD of net-next :)

Would it be a problem if I try and use the patch on top of a clean
3.1.6 kernel ?

/Bjarke

>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: David Miller @ 2011-12-29 23:48 UTC (permalink / raw)
  To: gurligebis; +Cc: romieu, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <CACPM=kVfsXgFhKheevTS1pm7kCoezKO3M+102O=PRbXzxebxxg@mail.gmail.com>

From: Bjarke Istrup Pedersen <gurligebis@gentoo.org>
Date: Fri, 30 Dec 2011 00:37:17 +0100

> Hmm, it seems like this problem isn't related to the driver, but
> related to the current HEAD of net-next :)

Please try this patch.

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 30de9e7..4a62c47 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -129,11 +129,14 @@ static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const voi
 	return neigh_create(&nd_tbl, daddr, dst->dev);
 }
 
-static int rt6_bind_neighbour(struct rt6_info *rt)
+static int rt6_bind_neighbour(struct rt6_info *rt, struct net_device *dev)
 {
-	struct neighbour *n = ip6_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
-	if (IS_ERR(n))
-		return PTR_ERR(n);
+	struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dev, &rt->rt6i_gateway);
+	if (!n) {
+		n = neigh_create(&nd_tbl, &rt->rt6i_gateway, dev);
+		if (IS_ERR(n))
+			return PTR_ERR(n);
+	}
 	dst_set_neighbour(&rt->dst, n);
 
 	return 0;
@@ -746,7 +749,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
 #endif
 
 	retry:
-		if (rt6_bind_neighbour(rt)) {
+		if (rt6_bind_neighbour(rt, rt->dst.dev)) {
 			struct net *net = dev_net(rt->dst.dev);
 			int saved_rt_min_interval =
 				net->ipv6.sysctl.ip6_rt_gc_min_interval;
@@ -1397,7 +1400,7 @@ int ip6_route_add(struct fib6_config *cfg)
 		rt->rt6i_prefsrc.plen = 0;
 
 	if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
-		err = rt6_bind_neighbour(rt);
+		err = rt6_bind_neighbour(rt, dev);
 		if (err)
 			goto out;
 	}
@@ -2084,7 +2087,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 		rt->rt6i_flags |= RTF_ANYCAST;
 	else
 		rt->rt6i_flags |= RTF_LOCAL;
-	err = rt6_bind_neighbour(rt);
+	err = rt6_bind_neighbour(rt, rt->dst.dev);
 	if (err) {
 		dst_free(&rt->dst);
 		return ERR_PTR(err);

^ permalink raw reply related

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Francois Romieu @ 2011-12-29 23:53 UTC (permalink / raw)
  To: Bjarke Istrup Pedersen
  Cc: David Miller, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <CACPM=kVfsXgFhKheevTS1pm7kCoezKO3M+102O=PRbXzxebxxg@mail.gmail.com>

Bjarke Istrup Pedersen <gurligebis@gentoo.org> :
[...]
> Would it be a problem if I try and use the patch on top of a clean
> 3.1.6 kernel ?

You will have to "cd drivers/net && patch -p5 ..." as the paths are
different. Avoid suspend/resume/runtime PM.

-- 
Ueimor

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Bjarke Istrup Pedersen @ 2011-12-30  1:18 UTC (permalink / raw)
  To: David Miller; +Cc: romieu, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20111229.184842.664528940770120593.davem@davemloft.net>

2011/12/30 David Miller <davem@davemloft.net>:
> From: Bjarke Istrup Pedersen <gurligebis@gentoo.org>
> Date: Fri, 30 Dec 2011 00:37:17 +0100
>
>> Hmm, it seems like this problem isn't related to the driver, but
>> related to the current HEAD of net-next :)
>
> Please try this patch.
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 30de9e7..4a62c47 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -129,11 +129,14 @@ static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const voi
>        return neigh_create(&nd_tbl, daddr, dst->dev);
>  }
>
> -static int rt6_bind_neighbour(struct rt6_info *rt)
> +static int rt6_bind_neighbour(struct rt6_info *rt, struct net_device *dev)
>  {
> -       struct neighbour *n = ip6_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
> -       if (IS_ERR(n))
> -               return PTR_ERR(n);
> +       struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dev, &rt->rt6i_gateway);
> +       if (!n) {
> +               n = neigh_create(&nd_tbl, &rt->rt6i_gateway, dev);
> +               if (IS_ERR(n))
> +                       return PTR_ERR(n);
> +       }
>        dst_set_neighbour(&rt->dst, n);
>
>        return 0;
> @@ -746,7 +749,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
>  #endif
>
>        retry:
> -               if (rt6_bind_neighbour(rt)) {
> +               if (rt6_bind_neighbour(rt, rt->dst.dev)) {
>                        struct net *net = dev_net(rt->dst.dev);
>                        int saved_rt_min_interval =
>                                net->ipv6.sysctl.ip6_rt_gc_min_interval;
> @@ -1397,7 +1400,7 @@ int ip6_route_add(struct fib6_config *cfg)
>                rt->rt6i_prefsrc.plen = 0;
>
>        if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
> -               err = rt6_bind_neighbour(rt);
> +               err = rt6_bind_neighbour(rt, dev);
>                if (err)
>                        goto out;
>        }
> @@ -2084,7 +2087,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
>                rt->rt6i_flags |= RTF_ANYCAST;
>        else
>                rt->rt6i_flags |= RTF_LOCAL;
> -       err = rt6_bind_neighbour(rt);
> +       err = rt6_bind_neighbour(rt, rt->dst.dev);
>        if (err) {
>                dst_free(&rt->dst);
>                return ERR_PTR(err);

Hey David,

That patch works, now it boots fine :)
I tried the driver on the 3.1.6 kernel to make sure nothing not tested
is causing problems.

/Bjarke

> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Bjarke Istrup Pedersen @ 2011-12-30  1:21 UTC (permalink / raw)
  To: Francois Romieu
  Cc: David Miller, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20111229235312.GA27092@electric-eye.fr.zoreil.com>

2011/12/30 Francois Romieu <romieu@fr.zoreil.com>:
> Bjarke Istrup Pedersen <gurligebis@gentoo.org> :
> [...]
>> Would it be a problem if I try and use the patch on top of a clean
>> 3.1.6 kernel ?
>
> You will have to "cd drivers/net && patch -p5 ..." as the paths are
> different. Avoid suspend/resume/runtime PM.

The driver seems to be working fine on 3.1.6 - tried VPN'ing into my
network using my phone, and tried copying some files, which seems to
be working.
Not sure if it will be a problem when there is more bandwidth, but so
far it looks alot better.

The log is flodded with this debug info, in case you need it:

Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:08.0: lan0:
Interrupt, status 00000002
Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:06.0: wan0:
Interrupt, status 00000001
Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:06.0: wan0:
Interrupt, status 00000001
Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:08.0: lan0:
Interrupt, status 00000002
Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:08.0: lan0:
Interrupt, status 00000002
Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:08.0: lan0:
Interrupt, status 00000001
Dec 30 01:19:27 woodpecker kernel: via-rhine 0000:00:06.0: wan0:
Interrupt, status 00000002

Looking forward to seeing this in mainline, without the log spamming :)

/Bjarke

> --
> Ueimor
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* WTF is going with sock->file "allocation" by iscsi_target_login.c?
From: Al Viro @ 2011-12-30  1:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-fsdevel, open-iscsi, Nicholas Bellinger

In iscsi_target_setup_login_socket()
        /*
         * The SCTP stack needs struct socket->file.
         */
        if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
            (np->np_network_transport == ISCSI_SCTP_UDP)) {
                if (!sock->file) {
                        sock->file = kzalloc(sizeof(struct file), GFP_KERNEL);
and similar bit slightly below are utterly bogus.  In the best case the comment
is BS and SCTP actually doesn't give a damn about having non-NULL sock->file.
Assuming that this Fine Piece Of Software actually manages to deal with
all codepaths that might kill that sock, that is.

In the worst case, we end up leaking stuff or passing that object to something
that expect real struct file *.  In which case we are well and truly screwed.

Could somebody familiar with the code in question (iscsi and sctp) explain
what the hell is going on?

^ permalink raw reply

* Re: A pure virtual nic
From: Li, Zhen-Hua @ 2011-12-30  1:51 UTC (permalink / raw)
  To: Michał Mirosław; +Cc: Linux NetDev
In-Reply-To: <CAHXqBFKstJCQ4rif6S7mNuQUzFjJ1wfRKAksFePJyBoTw0YTfg@mail.gmail.com>

I plan to add some protocols to it. For example, HTTP Proxy packet
analysis. So user-space programs can use an NIC in common way in a
proxy needed environment.



2011/12/29 Michał Mirosław <mirqus@gmail.com>:
> 2011/12/29 Zhen-Hua Li <lizhenhua.dev@gmail.com>:
>> I have opened a project in SourceForge, it provides a pure virtual
>> ethernet adapter.  If you are interested to join it, please mail me.
>
> Is veth or tap (both in vanilla kernel) not enough for you? What are
> the differences?
>
> Best Regards,
> Michał Mirosław

^ 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