* Re: [PATCHv2 1/2] bonding: fix netdev event NULL pointer dereference
From: David Miller @ 2013-04-11 17:28 UTC (permalink / raw)
To: nikolay; +Cc: netdev, andy, fubar
In-Reply-To: <1365687905-1053-1-git-send-email-nikolay@redhat.com>
When you repost a patch that's part of a series, you must resubmit all
patches in that series, not just the one that changed.
You should also provide a header posting "[PATCH 0/N] ..." that explains
the high level purpose and intent of the patch set.
^ permalink raw reply
* Re: [PATCH iproute2 v2] vxlan: Allow setting destination to unicast address.
From: David Miller @ 2013-04-11 17:30 UTC (permalink / raw)
To: stephen; +Cc: atzm, netdev
In-Reply-To: <20130411082438.7fe3421b@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Thu, 11 Apr 2013 08:24:38 -0700
> On Thu, 11 Apr 2013 19:17:54 +0900
> Atzm Watanabe <atzm@stratosphere.co.jp> wrote:
>
>> diff --git a/include/linux/if_link.h b/include/linux/if_link.h
>> index 40167af..0bf03dc 100644
>> --- a/include/linux/if_link.h
>> +++ b/include/linux/if_link.h
>> @@ -296,6 +296,7 @@ enum {
>> IFLA_VXLAN_GROUP,
>> IFLA_VXLAN_LINK,
>> IFLA_VXLAN_LOCAL,
>> + IFLA_VXLAN_REMOTE,
>> IFLA_VXLAN_TTL,
>> IFLA_VXLAN_TOS,
>
> You can't insert another value into the middle of an enum list.
> It changes the kernel-userspace ABI values.
Right.
^ permalink raw reply
* Re: [PATCH RFC] spinlock: split out debugging check from spin_lock_mutex
From: Bart Van Assche @ 2013-04-11 17:31 UTC (permalink / raw)
To: Neil Horman; +Cc: David Miller, netdev
In-Reply-To: <1365693486-6315-1-git-send-email-nhorman@tuxdriver.com>
On 04/11/13 17:18, Neil Horman wrote:
> Bart, this patch should fix your problem. Could you please test it and confirm?
The fails to build on my setup after having applied that patch:
kernel/mutex.c: In function ‘__mutex_trylock_slowpath’:
kernel/mutex.c:446:2: error: implicit declaration of function
‘spin_unlock_mutex_raw’ [-Werror=implicit-function-declaration]
Bart.
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: David Miller @ 2013-04-11 17:31 UTC (permalink / raw)
To: sebastian.hesselbarth
Cc: w, andrew, jason, benh, linux-kernel, florian, smoch, paulus,
buytenh, dale, netdev, linuxppc-dev, linux-arm-kernel
In-Reply-To: <CABJ1b_TRxm97DKJLP_h0VwMJvcYmSpjoJvtg1KvBNGah=VzqMQ@mail.gmail.com>
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Date: Thu, 11 Apr 2013 17:27:03 +0200
> On Thu, Apr 11, 2013 at 5:03 PM, Willy Tarreau <w@1wt.eu> wrote:
>> On Thu, Apr 11, 2013 at 04:47:49PM +0200, Sebastian Hesselbarth wrote:
>>> I tried todays net-next on top of 3.9-rc6 without any gro patch, with
>>> the initial
>>> patch (Soeren) and your proposed patch (Willy). The results show that
>>> both patches
>>> allow a significant increase in throughput compared to
>>> netif_receive_skb (!gro, !lro)
>>> alone. Having gro with lro disabled gives some 2% more throughput
>>> compared to lro only.
>>
>> Indeed this is consistent with my memories, since Eric improved the
>> GRO path, it became faster than LRO on this chip.
>
> I don't have a strong opinion on whether Soeren's or your proposal should
> be submitted. But I insist on having one of them in, as GRO significantly
> improves the common use case, is enabled by default, and not as
> constrained as LRO.
I think, as per other drivers, LRO should be eliminated completely from
all drivers, including this one, and GRO used exclusively instead.
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Eric Dumazet @ 2013-04-11 17:35 UTC (permalink / raw)
To: David Miller
Cc: sebastian.hesselbarth, w, andrew, jason, benh, linux-kernel,
florian, smoch, paulus, buytenh, dale, netdev, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <20130411.133119.913809939413807690.davem@davemloft.net>
On Thu, 2013-04-11 at 13:31 -0400, David Miller wrote:
> I think, as per other drivers, LRO should be eliminated completely from
> all drivers, including this one, and GRO used exclusively instead.
This would be awesome.
AFAIK current LRO users are :
drivers/infiniband/hw/nes/nes_hw.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/pasemi/pasemi_mac.c
^ permalink raw reply
* Re: [PATCH iproute2 v2] vxlan: Allow setting destination to unicast address.
From: Ben Hutchings @ 2013-04-11 17:48 UTC (permalink / raw)
To: Atzm Watanabe; +Cc: netdev, Stephen Hemminger
In-Reply-To: <87li8pmkvh.wl%atzm@stratosphere.co.jp>
On Thu, 2013-04-11 at 19:17 +0900, Atzm Watanabe wrote:
> This patch allows setting VXLAN destination to unicast address.
> It allows that VXLAN can be used as peer-to-peer tunnel without
> multicast.
>
> v2: use a new argument "remote" instead of "group" based by
> Stephen Hemminger's comments.
>
> Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
[...]
> --- a/ip/iplink_vxlan.c
> +++ b/ip/iplink_vxlan.c
> @@ -23,7 +23,8 @@
>
> static void explain(void)
> {
> - fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ local ADDR ]\n");
> + fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ remote ADDR ]\n");
[...]
Shouldn't that be "[ group|remote ADDR ]", to show that you can specify
one or the other?
Ben.
--
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: [PATCH RFC] spinlock: split out debugging check from spin_lock_mutex
From: Christoph Paasch @ 2013-04-11 17:51 UTC (permalink / raw)
To: Neil Horman; +Cc: g, Bart Van Assche, David Miller, netdev
In-Reply-To: <20130411170404.GE8986@neilslaptop.think-freely.org>
On Thursday 11 April 2013 13:04:05 Neil Horman wrote:
> I dont believe the deadlock you describe can happen. The spin_lock_mutex
> operation disables irqs on the local cpu with local_irq_save, so we won't
> loose the cpu while we're holding the spinlock. Likewise we don't restore
> the irq flags until after we release said lock. Once we have the mutex, if
> we're preempted by another path that goes through the netpoll_poll_dev
> path, then we hit the trylock api call. The spinlock is either released or
> held on another cpu (read: no deadlock), and if the mutex is held, then the
> trylock simply fails.
Thanks for explaining this to me. I was looking for a local_bh_disable() - but
local_irq_save does the job too.
Thanks,
Christoph
--
IP Networking Lab --- http://inl.info.ucl.ac.be
MultiPath TCP in the Linux Kernel --- http://multipath-tcp.org
UCLouvain
--
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Willy Tarreau @ 2013-04-11 17:51 UTC (permalink / raw)
To: David Miller
Cc: andrew, jason, benh, linux-kernel, smoch, paulus,
linux-arm-kernel, dale, netdev, linuxppc-dev, florian, buytenh,
sebastian.hesselbarth
In-Reply-To: <20130411.133119.913809939413807690.davem@davemloft.net>
On Thu, Apr 11, 2013 at 01:31:19PM -0400, David Miller wrote:
> From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Date: Thu, 11 Apr 2013 17:27:03 +0200
>
> > On Thu, Apr 11, 2013 at 5:03 PM, Willy Tarreau <w@1wt.eu> wrote:
> >> On Thu, Apr 11, 2013 at 04:47:49PM +0200, Sebastian Hesselbarth wrote:
> >>> I tried todays net-next on top of 3.9-rc6 without any gro patch, with
> >>> the initial
> >>> patch (Soeren) and your proposed patch (Willy). The results show that
> >>> both patches
> >>> allow a significant increase in throughput compared to
> >>> netif_receive_skb (!gro, !lro)
> >>> alone. Having gro with lro disabled gives some 2% more throughput
> >>> compared to lro only.
> >>
> >> Indeed this is consistent with my memories, since Eric improved the
> >> GRO path, it became faster than LRO on this chip.
> >
> > I don't have a strong opinion on whether Soeren's or your proposal should
> > be submitted. But I insist on having one of them in, as GRO significantly
> > improves the common use case, is enabled by default, and not as
> > constrained as LRO.
>
> I think, as per other drivers, LRO should be eliminated completely from
> all drivers, including this one, and GRO used exclusively instead.
Eric provided me with one such experimental patch in the past for this
driver. It worked for me but we never tried to clean it up to propose
it for inclusion.
If anyone is interested, I might still have it in experimental shape.
Willy
^ permalink raw reply
* Re: [PATCH RFC] spinlock: split out debugging check from spin_lock_mutex
From: Neil Horman @ 2013-04-11 17:52 UTC (permalink / raw)
To: Bart Van Assche; +Cc: David Miller, netdev
In-Reply-To: <5166F35B.1040200@acm.org>
On Thu, Apr 11, 2013 at 07:31:07PM +0200, Bart Van Assche wrote:
> On 04/11/13 17:18, Neil Horman wrote:
> >Bart, this patch should fix your problem. Could you please test it and confirm?
>
> The fails to build on my setup after having applied that patch:
>
> kernel/mutex.c: In function ‘__mutex_trylock_slowpath’:
> kernel/mutex.c:446:2: error: implicit declaration of function
> ‘spin_unlock_mutex_raw’ [-Werror=implicit-function-declaration]
>
Strage, not sure why, although I didn't explicitly test it myself. I'll take a
look this evening and fix it up for you.
Neil
> Bart.
>
^ permalink raw reply
* Re: [PATCH] tcp: Reallocate headroom if it would overflow csum_start
From: Ben Hutchings @ 2013-04-11 17:52 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Thomas Graf, davem, netdev
In-Reply-To: <1365695394.3887.162.camel@edumazet-glaptop>
On Thu, 2013-04-11 at 08:49 -0700, Eric Dumazet wrote:
> On Thu, 2013-04-11 at 13:19 +0200, Thomas Graf wrote:
> > If a TCP retransmission gets partially ACKed and collapsed multiple
> > times it is possible for the headroom to grow beyond 64K which will
> > overflow the 16bit skb->csum_start which is based on the start of
> > the headroom. It has been observed rarely in the wild with IPoIB due
> > to the 64K MTU.
> >
> > Verify if the acking and collapsing resulted in a headroom exceeding
> > what csum_start can cover and reallocate the headroom if so.
> >
> > LLNL has been running the patch for a while and has not seen the
> > problem occur since.
> >
> > A big thank you to Jim Foraker <foraker1@llnl.gov> and the team at
> > LLNL for helping out with the investigation and testing.
> >
> > Reported-by: Jim Foraker <foraker1@llnl.gov>
> > Signed-off-by: Thomas Graf <tgraf@suug.ch>
> > ---
> > v2: reallocate headroom instead of preventing further collapsing
> >
> > net/ipv4/tcp_output.c | 7 +++++--
> > 1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> > index b44cf81..bf6ceb7 100644
> > --- a/net/ipv4/tcp_output.c
> > +++ b/net/ipv4/tcp_output.c
> > @@ -2388,8 +2388,11 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
> > */
> > TCP_SKB_CB(skb)->when = tcp_time_stamp;
> >
> > - /* make sure skb->data is aligned on arches that require it */
> > - if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
> > + /* make sure skb->data is aligned on arches that require it
> > + * and check if ack-trimming & collapsing extended the headroom
> > + * beyond what csum_start can cover. */
> > + if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3) ||
> > + skb_headroom(skb) >= 0xFFFF)) {
> > struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
> > GFP_ATOMIC);
> > return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
>
> Strange... It was tested on an arch with NET_IP_ALIGN == 2 I presume ?
>
> This fix should also be done for other arches (x86 for example)
>
> I would code the condition like that instead
>
> if ((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
> skb_headroom(skb) >= 0xFFFF)
You dropped the unlikely() and added redundant parentheses, which may be
clearer but is still equivalent.
Ben.
--
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: [RFC PATCH] udp: don't rereference dst_entry dev pointer on rcv
From: Eric Dumazet @ 2013-04-11 17:53 UTC (permalink / raw)
To: Tom Parkin; +Cc: David Miller, netdev
In-Reply-To: <1365697961.3887.176.camel@edumazet-glaptop>
On Thu, 2013-04-11 at 09:32 -0700, Eric Dumazet wrote:
> Short update : I do not understand yet why this patch is not working.
>
> Normally, the reassembled packet should get the dst from the last skb
> (the one completing the packet)...
>
> I have to make more experiments.
OK I think I've nailed it, please try following patch (I tried it on
net-next, but it should apply on previous kernels)
Thanks !
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 9385206..f8f1a87 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -494,9 +494,16 @@ found:
qp->q.max_size = skb->len + ihl;
if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
- qp->q.meat == qp->q.len)
- return ip_frag_reasm(qp, prev, dev);
+ qp->q.meat == qp->q.len) {
+ unsigned long dst_save = skb->_skb_refdst;
+ skb->_skb_refdst = 0;
+ err = ip_frag_reasm(qp, prev, dev);
+ skb->_skb_refdst = dst_save;
+ return err;
+ }
+
+ skb_dst_drop(skb);
inet_frag_lru_move(&qp->q);
return -EINPROGRESS;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index e6e44ce..aac7fa5 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -342,9 +342,17 @@ found:
}
if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
- fq->q.meat == fq->q.len)
- return ip6_frag_reasm(fq, prev, dev);
+ fq->q.meat == fq->q.len) {
+ int err;
+ unsigned long dstsave = skb->_skb_refdst;
+
+ skb->_skb_refdst = 0;
+ err = ip6_frag_reasm(fq, prev, dev);
+ skb->_skb_refdst = dstsave;
+ return err;
+ }
+ skb_dst_drop(skb);
inet_frag_lru_move(&fq->q);
return -1;
^ permalink raw reply related
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Ben Hutchings @ 2013-04-11 17:55 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Soeren Moch, David S. Miller, Lennert Buytenhek, Andrew Lunn,
Jason Cooper, Florian Fainelli, Benjamin Herrenschmidt,
Paul Mackerras, Dale Farnsworth, netdev, linux-arm-kernel,
linuxppc-dev, linux-kernel
In-Reply-To: <1365684023-9967-1-git-send-email-sebastian.hesselbarth@gmail.com>
On Thu, 2013-04-11 at 14:40 +0200, Sebastian Hesselbarth wrote:
> This patch adds GRO support to mv643xx_eth by making it invoke
> napi_gro_receive instead of netif_receive_skb.
The inet_lro support should be removed at the same time; inet_lro is now
deprecated and there should be no need to keep both of them.
Ben.
> Signed-off-by: Soeren Moch <smoch@web.de>
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Lennert Buytenhek <buytenh@wantstofly.org>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Florian Fainelli <florian@openwrt.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Dale Farnsworth <dale@farnsworth.org>
> Cc: netdev@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-kernel@vger.kernel.org
> ---
> drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index 305038f..c850d04 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -604,7 +604,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
> lro_receive_skb(&rxq->lro_mgr, skb, (void *)cmd_sts);
> lro_flush_needed = 1;
> } else
> - netif_receive_skb(skb);
> + napi_gro_receive(&mp->napi, skb);
>
> continue;
>
--
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: [PATCH] tcp: Reallocate headroom if it would overflow csum_start
From: Eric Dumazet @ 2013-04-11 17:57 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Thomas Graf, davem, netdev
In-Reply-To: <1365702765.7355.3.camel@bwh-desktop.uk.solarflarecom.com>
On Thu, 2013-04-11 at 18:52 +0100, Ben Hutchings wrote:
> On Thu, 2013-04-11 at 08:49 -0700, Eric Dumazet wrote:
> > On Thu, 2013-04-11 at 13:19 +0200, Thomas Graf wrote:
> > > If a TCP retransmission gets partially ACKed and collapsed multiple
> > > times it is possible for the headroom to grow beyond 64K which will
> > > overflow the 16bit skb->csum_start which is based on the start of
> > > the headroom. It has been observed rarely in the wild with IPoIB due
> > > to the 64K MTU.
> > >
> > > Verify if the acking and collapsing resulted in a headroom exceeding
> > > what csum_start can cover and reallocate the headroom if so.
> > >
> > > LLNL has been running the patch for a while and has not seen the
> > > problem occur since.
> > >
> > > A big thank you to Jim Foraker <foraker1@llnl.gov> and the team at
> > > LLNL for helping out with the investigation and testing.
> > >
> > > Reported-by: Jim Foraker <foraker1@llnl.gov>
> > > Signed-off-by: Thomas Graf <tgraf@suug.ch>
> > > ---
> > > v2: reallocate headroom instead of preventing further collapsing
> > >
> > > net/ipv4/tcp_output.c | 7 +++++--
> > > 1 file changed, 5 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> > > index b44cf81..bf6ceb7 100644
> > > --- a/net/ipv4/tcp_output.c
> > > +++ b/net/ipv4/tcp_output.c
> > > @@ -2388,8 +2388,11 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
> > > */
> > > TCP_SKB_CB(skb)->when = tcp_time_stamp;
> > >
> > > - /* make sure skb->data is aligned on arches that require it */
> > > - if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
> > > + /* make sure skb->data is aligned on arches that require it
> > > + * and check if ack-trimming & collapsing extended the headroom
> > > + * beyond what csum_start can cover. */
> > > + if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3) ||
> > > + skb_headroom(skb) >= 0xFFFF)) {
> > > struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
> > > GFP_ATOMIC);
> > > return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
> >
> > Strange... It was tested on an arch with NET_IP_ALIGN == 2 I presume ?
> >
> > This fix should also be done for other arches (x86 for example)
> >
> > I would code the condition like that instead
> >
> > if ((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
> > skb_headroom(skb) >= 0xFFFF)
>
> You dropped the unlikely() and added redundant parentheses, which may be
> clearer but is still equivalent.
I see what you mean...
I just don't like
if (A && B || C)
I prefer in this case
if ((A && B) || C)
Then add the unlikely() if we really care in this _ultra_ slow path
if (unlikely((A && B) || C))
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Eric Dumazet @ 2013-04-11 17:59 UTC (permalink / raw)
To: Willy Tarreau
Cc: David Miller, sebastian.hesselbarth, andrew, jason, benh,
linux-kernel, florian, smoch, paulus, buytenh, dale, netdev,
linuxppc-dev, linux-arm-kernel
In-Reply-To: <20130411175147.GN1910@1wt.eu>
On Thu, 2013-04-11 at 19:51 +0200, Willy Tarreau wrote:
> Eric provided me with one such experimental patch in the past for this
> driver. It worked for me but we never tried to clean it up to propose
> it for inclusion.
>
> If anyone is interested, I might still have it in experimental shape.
We are interested a lot ;)
Thanks !
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Willy Tarreau @ 2013-04-11 18:02 UTC (permalink / raw)
To: Eric Dumazet
Cc: andrew, jason, benh, linux-kernel, florian, smoch, paulus,
linux-arm-kernel, dale, netdev, linuxppc-dev, David Miller,
buytenh, sebastian.hesselbarth
In-Reply-To: <1365703155.3887.184.camel@edumazet-glaptop>
On Thu, Apr 11, 2013 at 10:59:15AM -0700, Eric Dumazet wrote:
> On Thu, 2013-04-11 at 19:51 +0200, Willy Tarreau wrote:
>
> > Eric provided me with one such experimental patch in the past for this
> > driver. It worked for me but we never tried to clean it up to propose
> > it for inclusion.
> >
> > If anyone is interested, I might still have it in experimental shape.
>
> We are interested a lot ;)
Just found it in one of my local branches :-)
Here it is. It was experimental. At first glance, I'm seeing it does not
remove NETIF_F_LRO as we used it for experimentation only, but that's
a trivial thing to fix.
Original work by you Eric, tested by me on 3.6.
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index ea2cedc..81a6cb0 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -55,9 +55,9 @@
#include <linux/mv643xx_eth.h>
#include <linux/io.h>
#include <linux/types.h>
-#include <linux/inet_lro.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/interrupt.h>
static char mv643xx_eth_driver_name[] = "mv643xx_eth";
static char mv643xx_eth_driver_version[] = "1.4";
@@ -343,12 +343,6 @@ struct mib_counters {
u32 rx_overrun;
};
-struct lro_counters {
- u32 lro_aggregated;
- u32 lro_flushed;
- u32 lro_no_desc;
-};
-
struct rx_queue {
int index;
@@ -363,8 +357,6 @@ struct rx_queue {
int rx_desc_area_size;
void **rx_data;
unsigned int frag_size;
- struct net_lro_mgr lro_mgr;
- struct net_lro_desc lro_arr[8];
};
struct tx_queue {
@@ -400,8 +392,6 @@ struct mv643xx_eth_private {
spinlock_t mib_counters_lock;
struct mib_counters mib_counters;
- struct lro_counters lro_counters;
-
struct work_struct tx_timeout_task;
struct napi_struct napi;
@@ -533,33 +523,6 @@ static void txq_maybe_wake(struct tx_queue *txq)
}
-/* rx napi ******************************************************************/
-static int
-mv643xx_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph,
- u64 *hdr_flags, void *priv)
-{
- unsigned long cmd_sts = (unsigned long)priv;
-
- /*
- * Make sure that this packet is Ethernet II, is not VLAN
- * tagged, is IPv4, has a valid IP header, and is TCP.
- */
- if ((cmd_sts & (RX_IP_HDR_OK | RX_PKT_IS_IPV4 |
- RX_PKT_IS_ETHERNETV2 | RX_PKT_LAYER4_TYPE_MASK |
- RX_PKT_IS_VLAN_TAGGED)) !=
- (RX_IP_HDR_OK | RX_PKT_IS_IPV4 |
- RX_PKT_IS_ETHERNETV2 | RX_PKT_LAYER4_TYPE_TCP_IPV4))
- return -1;
-
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, ip_hdrlen(skb));
- *iphdr = ip_hdr(skb);
- *tcph = tcp_hdr(skb);
- *hdr_flags = LRO_IPV4 | LRO_TCP;
-
- return 0;
-}
-
static void mv_frag_free(const struct rx_queue *rxq, void *data)
{
if (rxq->frag_size)
@@ -568,14 +531,12 @@ static void mv_frag_free(const struct rx_queue *rxq, void *data)
kfree(data);
}
-static int rxq_process(struct rx_queue *rxq, int budget)
+static int rxq_process(struct napi_struct *napi, struct rx_queue *rxq, int budget)
{
struct mv643xx_eth_private *mp = rxq_to_mp(rxq);
struct net_device_stats *stats = &mp->dev->stats;
- int lro_flush_needed;
int rx;
- lro_flush_needed = 0;
rx = 0;
while (rx < budget && rxq->rx_desc_count) {
struct rx_desc *rx_desc;
@@ -646,12 +607,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->protocol = eth_type_trans(skb, mp->dev);
- if (skb->dev->features & NETIF_F_LRO &&
- skb->ip_summed == CHECKSUM_UNNECESSARY) {
- lro_receive_skb(&rxq->lro_mgr, skb, (void *)cmd_sts);
- lro_flush_needed = 1;
- } else
- netif_receive_skb(skb);
+ napi_gro_receive(napi, skb);
continue;
@@ -671,9 +627,6 @@ err:
dev_kfree_skb(skb);
}
- if (lro_flush_needed)
- lro_flush_all(&rxq->lro_mgr);
-
if (rx < budget)
mp->work_rx &= ~(1 << rxq->index);
@@ -723,7 +676,6 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
rxq->rx_data[rx] = data;
wmb();
rx_desc->cmd_sts = BUFFER_OWNED_BY_DMA | RX_ENABLE_INTERRUPT;
-
}
if (refilled < budget)
@@ -1214,26 +1166,6 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
return stats;
}
-static void mv643xx_eth_grab_lro_stats(struct mv643xx_eth_private *mp)
-{
- u32 lro_aggregated = 0;
- u32 lro_flushed = 0;
- u32 lro_no_desc = 0;
- int i;
-
- for (i = 0; i < mp->rxq_count; i++) {
- struct rx_queue *rxq = mp->rxq + i;
-
- lro_aggregated += rxq->lro_mgr.stats.aggregated;
- lro_flushed += rxq->lro_mgr.stats.flushed;
- lro_no_desc += rxq->lro_mgr.stats.no_desc;
- }
-
- mp->lro_counters.lro_aggregated = lro_aggregated;
- mp->lro_counters.lro_flushed = lro_flushed;
- mp->lro_counters.lro_no_desc = lro_no_desc;
-}
-
static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset)
{
return rdl(mp, MIB_COUNTERS(mp->port_num) + offset);
@@ -1397,10 +1329,6 @@ struct mv643xx_eth_stats {
{ #m, FIELD_SIZEOF(struct mib_counters, m), \
-1, offsetof(struct mv643xx_eth_private, mib_counters.m) }
-#define LROSTAT(m) \
- { #m, FIELD_SIZEOF(struct lro_counters, m), \
- -1, offsetof(struct mv643xx_eth_private, lro_counters.m) }
-
static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
SSTAT(rx_packets),
SSTAT(tx_packets),
@@ -1442,9 +1370,6 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
MIBSTAT(late_collision),
MIBSTAT(rx_discard),
MIBSTAT(rx_overrun),
- LROSTAT(lro_aggregated),
- LROSTAT(lro_flushed),
- LROSTAT(lro_no_desc),
};
static int
@@ -1642,7 +1567,6 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev,
mv643xx_eth_get_stats(dev);
mib_counters_update(mp);
- mv643xx_eth_grab_lro_stats(mp);
for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) {
const struct mv643xx_eth_stats *stat;
@@ -1915,19 +1839,6 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index)
nexti * sizeof(struct rx_desc);
}
- rxq->lro_mgr.dev = mp->dev;
- memset(&rxq->lro_mgr.stats, 0, sizeof(rxq->lro_mgr.stats));
- rxq->lro_mgr.features = LRO_F_NAPI;
- rxq->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
- rxq->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
- rxq->lro_mgr.max_desc = ARRAY_SIZE(rxq->lro_arr);
- rxq->lro_mgr.max_aggr = 32;
- rxq->lro_mgr.frag_align_pad = 0;
- rxq->lro_mgr.lro_arr = rxq->lro_arr;
- rxq->lro_mgr.get_skb_header = mv643xx_get_skb_header;
-
- memset(&rxq->lro_arr, 0, sizeof(rxq->lro_arr));
-
return 0;
@@ -2192,7 +2103,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
work_done += txq_reclaim(mp->txq + queue, work_tbd, 0);
txq_maybe_wake(mp->txq + queue);
} else if (mp->work_rx & queue_mask) {
- work_done += rxq_process(mp->rxq + queue, work_tbd);
+ work_done += rxq_process(napi, mp->rxq + queue, work_tbd);
} else if (!mp->oom && (mp->work_rx_refill & queue_mask)) {
work_done += rxq_refill(mp->rxq + queue, work_tbd);
} else {
Regards,
Willy
^ permalink raw reply related
* Re: [PATCH repost for-3.9] pci: avoid work_on_cpu for nested SRIOV probes
From: Tejun Heo @ 2013-04-11 18:05 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Or Gerlitz, Ming Lei, Greg Kroah-Hartman, David Miller,
Roland Dreier, netdev, Yan Burman, Jack Morgenstein,
Bjorn Helgaas, linux-pci
In-Reply-To: <20130411153030.GA22743@redhat.com>
Hello,
On Thu, Apr 11, 2013 at 06:30:30PM +0300, Michael S. Tsirkin wrote:
> The issue is that a driver, in it's probe function, calls
> pci_sriov_enable so a PF device probe causes VF probe (AKA nested
> probe). Each probe in pci_device_probe is (normally) run through
> work_on_cpu (this is to get the right numa node for memory allocated by
> the driver). In turn work_on_cpu does this internally:
>
> schedule_work_on(cpu, &wfc.work);
> flush_work(&wfc.work);
>
> So if you are running probe on CPU1, and cause another
> probe on the same CPU, this will try to flush
> workqueue from inside same workqueue which of course
> deadlocks.
>
> Nested probing might be tricky to get right generally.
Hmm... how about adding a work_on_cpu_nested() which takes @subclass
argument? Wouldn't that be much cleaner?
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Sebastian Hesselbarth @ 2013-04-11 18:07 UTC (permalink / raw)
To: Ben Hutchings
Cc: Andrew Lunn, Jason Cooper, Benjamin Herrenschmidt, linux-kernel,
David S. Miller, Soeren Moch, Paul Mackerras, linux-arm-kernel,
Dale Farnsworth, netdev, linuxppc-dev, Florian Fainelli,
Lennert Buytenhek
In-Reply-To: <1365702955.7355.5.camel@bwh-desktop.uk.solarflarecom.com>
On 04/11/2013 07:55 PM, Ben Hutchings wrote:
> On Thu, 2013-04-11 at 14:40 +0200, Sebastian Hesselbarth wrote:
>> This patch adds GRO support to mv643xx_eth by making it invoke
>> napi_gro_receive instead of netif_receive_skb.
>
> The inet_lro support should be removed at the same time; inet_lro is now
> deprecated and there should be no need to keep both of them.
Ben,
I agree on removing it asap, but I also like to see GRO support
in. Maybe, we postpone lro removal just a little bit. I have just
started to look at mv643xx_eth and remember Marvell Orion SoCs are
not the only platform using it. I haven't heard a single word from
ppc guys, yet.
Willy just posted an experimental patch to remove lro. I'll have
a look at it and test it out on Dove.
Sebastian
^ permalink raw reply
* Re: [PATCH] net: usb: active URB submitted multiple times
From: Petko Manolov @ 2013-04-11 18:44 UTC (permalink / raw)
To: Dan Williams; +Cc: David Miller, netdev, linux-kernel, Sarah Sharp
In-Reply-To: <1365698297.22668.5.camel@dcbw.foobar.com>
On Thu, 11 Apr 2013, Dan Williams wrote:
> On Thu, 2013-04-11 at 10:09 +0300, Petko Manolov wrote:
> > From: Petko Manolov <petkan@nucleusys.com>
> >
> > (For inclusion in 3.10, diff against latest net-next.)
>
> Your mail client replaced tabs with spaces. Make sure when adding the
> patch to the mail, you choose the "preformatted" option or whatever the
> client has to ensure that the patch text itself is not modified when
> pasting it into the mail.
The patch is indeed fucked up. Some tabs survived Apline's take on them,
but not nearly enough. I am sorry for the noise. It's been a while since
i last submitted a patch. Lets hope third time will be the charm...
cheers,
Petko
^ permalink raw reply
* [PATCH v2] can: sja1000: fix endian on arm
From: Christoph Fritz @ 2013-04-11 18:44 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde, Rob Herring, Grant Likely,
linux-can, netdev@vger.kernel.org, Andreas Larsson, Hans J. Koch,
Bill Pemberton, Daniel Mack
In-Reply-To: <5162CCB5.3000605@pengutronix.de>
To get correct endian on arm cpus while reading device tree properties,
this patch replaces of_get_property() with of_property_read_u32().
Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
---
drivers/net/can/sja1000/sja1000_of_platform.c | 32 ++++++++++++-------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 6433b81..dd8b031 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -96,8 +96,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
struct net_device *dev;
struct sja1000_priv *priv;
struct resource res;
- const u32 *prop;
- int err, irq, res_size, prop_size;
+ u32 prop;
+ int err, irq, res_size;
void __iomem *base;
err = of_address_to_resource(np, 0, &res);
@@ -138,27 +138,27 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
priv->read_reg = sja1000_ofp_read_reg;
priv->write_reg = sja1000_ofp_write_reg;
- prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->can.clock.freq = *prop / 2;
+ err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
+ if (!err)
+ priv->can.clock.freq = prop / 2;
else
priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
- prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= *prop & OCR_MODE_MASK;
+ err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
+ if (!err)
+ priv->ocr |= prop & OCR_MODE_MASK;
else
priv->ocr |= OCR_MODE_NORMAL; /* default */
- prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+ err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
+ if (!err)
+ priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
else
priv->ocr |= OCR_TX0_PULLDOWN; /* default */
- prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)) && *prop) {
- u32 divider = priv->can.clock.freq * 2 / *prop;
+ err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
+ if (!err) {
+ u32 divider = priv->can.clock.freq * 2 / prop;
if (divider > 1)
priv->cdr |= divider / 2 - 1;
@@ -168,8 +168,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
priv->cdr |= CDR_CLK_OFF; /* default */
}
- prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
- if (!prop)
+ err = of_property_read_u32(np, "nxp,no-comparator-bypass", &prop);
+ if (err)
priv->cdr |= CDR_CBP; /* default */
priv->irq_flags = IRQF_SHARED;
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v2] can: sja1000: fix endian on arm
From: Marc Kleine-Budde @ 2013-04-11 18:47 UTC (permalink / raw)
To: Christoph Fritz
Cc: Wolfgang Grandegger, Rob Herring, Grant Likely, linux-can,
netdev@vger.kernel.org, Andreas Larsson, Hans J. Koch,
Bill Pemberton, Daniel Mack
In-Reply-To: <1365705884.4136.5.camel@mars>
[-- Attachment #1: Type: text/plain, Size: 3441 bytes --]
On 04/11/2013 08:44 PM, Christoph Fritz wrote:
> To get correct endian on arm cpus while reading device tree properties,
> this patch replaces of_get_property() with of_property_read_u32().
>
> Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
looks good, one nitpick inline
> ---
> drivers/net/can/sja1000/sja1000_of_platform.c | 32 ++++++++++++-------------
> 1 file changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
> index 6433b81..dd8b031 100644
> --- a/drivers/net/can/sja1000/sja1000_of_platform.c
> +++ b/drivers/net/can/sja1000/sja1000_of_platform.c
> @@ -96,8 +96,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
> struct net_device *dev;
> struct sja1000_priv *priv;
> struct resource res;
> - const u32 *prop;
> - int err, irq, res_size, prop_size;
> + u32 prop;
> + int err, irq, res_size;
> void __iomem *base;
>
> err = of_address_to_resource(np, 0, &res);
> @@ -138,27 +138,27 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
> priv->read_reg = sja1000_ofp_read_reg;
> priv->write_reg = sja1000_ofp_write_reg;
>
> - prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
> - if (prop && (prop_size == sizeof(u32)))
> - priv->can.clock.freq = *prop / 2;
> + err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
> + if (!err)
> + priv->can.clock.freq = prop / 2;
> else
> priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
>
> - prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
> - if (prop && (prop_size == sizeof(u32)))
> - priv->ocr |= *prop & OCR_MODE_MASK;
> + err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
> + if (!err)
> + priv->ocr |= prop & OCR_MODE_MASK;
> else
> priv->ocr |= OCR_MODE_NORMAL; /* default */
>
> - prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
> - if (prop && (prop_size == sizeof(u32)))
> - priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
> + err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
> + if (!err)
> + priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
> else
> priv->ocr |= OCR_TX0_PULLDOWN; /* default */
>
> - prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
> - if (prop && (prop_size == sizeof(u32)) && *prop) {
> - u32 divider = priv->can.clock.freq * 2 / *prop;
> + err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
> + if (!err) {
> + u32 divider = priv->can.clock.freq * 2 / prop;
>
> if (divider > 1)
> priv->cdr |= divider / 2 - 1;
> @@ -168,8 +168,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
> priv->cdr |= CDR_CLK_OFF; /* default */
> }
>
> - prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
> - if (!prop)
> + err = of_property_read_u32(np, "nxp,no-comparator-bypass", &prop);
What about using of_property_read_bool instead?
> + if (err)
> priv->cdr |= CDR_CBP; /* default */
>
> priv->irq_flags = IRQF_SHARED;
>
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]
^ permalink raw reply
* Re: [PATCH v2] can: sja1000: fix endian on arm
From: Christoph Fritz @ 2013-04-11 18:53 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: Wolfgang Grandegger, Rob Herring, Grant Likely, linux-can,
netdev@vger.kernel.org, Andreas Larsson, Hans J. Koch,
Bill Pemberton, Daniel Mack
In-Reply-To: <51670532.5060101@pengutronix.de>
On Thu, 2013-04-11 at 20:47 +0200, Marc Kleine-Budde wrote:
> On 04/11/2013 08:44 PM, Christoph Fritz wrote:
> > To get correct endian on arm cpus while reading device tree properties,
> > this patch replaces of_get_property() with of_property_read_u32().
> >
> > Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
>
> looks good, one nitpick inline
>
> > ---
> > drivers/net/can/sja1000/sja1000_of_platform.c | 32 ++++++++++++-------------
> > 1 file changed, 16 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
> > @@ -168,8 +168,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
> > priv->cdr |= CDR_CLK_OFF; /* default */
> > }
> >
> > - prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
> > - if (!prop)
> > + err = of_property_read_u32(np, "nxp,no-comparator-bypass", &prop);
>
> What about using of_property_read_bool instead?
Yeah, that would be better, thanks - let me re-roll this.
^ permalink raw reply
* [PATCH RESEND] tcp: incoming connections might use wrong route under synflood
From: Dmitry Popov @ 2013-04-11 18:55 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy
Cc: netdev, linux-kernel
There is a bug in cookie_v4_check (net/ipv4/syncookies.c):
flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk),
(opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
ireq->loc_addr, th->source, th->dest);
Here we do not respect sk->sk_bound_dev_if, therefore wrong dst_entry may be
taken. This dst_entry is used by new socket (get_cookie_sock ->
tcp_v4_syn_recv_sock), so its packets may take the wrong path.
Signed-off-by: Dmitry Popov <dp@highloadlab.com>
---
net/ipv4/syncookies.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index ef54377..397e0f6 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -349,8 +349,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
* hasn't changed since we received the original syn, but I see
* no easy way to do this.
*/
- flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
- RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+ flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark,
+ RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk),
(opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
ireq->loc_addr, th->source, th->dest);
^ permalink raw reply related
* Re: [PATCH repost for-3.9] pci: avoid work_on_cpu for nested SRIOV probes
From: Michael S. Tsirkin @ 2013-04-11 18:58 UTC (permalink / raw)
To: Tejun Heo
Cc: Or Gerlitz, Ming Lei, Greg Kroah-Hartman, David Miller,
Roland Dreier, netdev, Yan Burman, Jack Morgenstein,
Bjorn Helgaas, linux-pci
In-Reply-To: <20130411180517.GJ17641@mtj.dyndns.org>
On Thu, Apr 11, 2013 at 11:05:17AM -0700, Tejun Heo wrote:
> Hello,
>
> On Thu, Apr 11, 2013 at 06:30:30PM +0300, Michael S. Tsirkin wrote:
> > The issue is that a driver, in it's probe function, calls
> > pci_sriov_enable so a PF device probe causes VF probe (AKA nested
> > probe). Each probe in pci_device_probe is (normally) run through
> > work_on_cpu (this is to get the right numa node for memory allocated by
> > the driver). In turn work_on_cpu does this internally:
> >
> > schedule_work_on(cpu, &wfc.work);
> > flush_work(&wfc.work);
> >
> > So if you are running probe on CPU1, and cause another
> > probe on the same CPU, this will try to flush
> > workqueue from inside same workqueue which of course
> > deadlocks.
> >
> > Nested probing might be tricky to get right generally.
>
> Hmm... how about adding a work_on_cpu_nested() which takes @subclass
> argument? Wouldn't that be much cleaner?
>
> Thanks.
Is that 3.9 material though?
> --
> tejun
^ permalink raw reply
* Re: [PATCH] net: usb: active URB submitted multiple times
From: Petko Manolov @ 2013-04-11 19:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel, Sarah Sharp, Dan Williams
In-Reply-To: <alpine.DEB.2.02.1304110956110.4237@fry>
From: Petko Manolov <petkan@nucleusys.com>
(For inclusion in 3.10, diff against latest net-next.)
Pegasus driver used single callback for sync and async control URBs.
Special flags were employed to distinguish between both, but due to flawed
logic (as Sarah Sharp spotted) it didn't always work. As a result of this
change [get|set]_registers() are now much simpler. Async write is also
leaner and does not use single, statically allocated memory for
usb_ctrlrequest, which is another potential race when asynchronously
submitting URBs.
The socket buffer pool for the receive path is now gone. It's existence
didn't make much difference (performance-wise) and the code is better off
without the spinlocks protecting it.
Largely duplicated code in routines reading and writing MII registers is
now packed in __mii_op().
Adding URL for the public pegasus git repository.
Signed-off-by: Petko Manolov <petkan@nucleusys.com>
---
MAINTAINERS | 6 +-
drivers/net/usb/pegasus.c | 601 +++++++++++++--------------------------------
drivers/net/usb/pegasus.h | 10 +-
3 files changed, 181 insertions(+), 436 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index c39bdc3..89cc8af 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8358,9 +8358,10 @@ S: Maintained
F: drivers/usb/serial/option.c
USB PEGASUS DRIVER
-M: Petko Manolov <petkan@users.sourceforge.net>
+M: Petko Manolov <petkan@nucleusys.com>
L: linux-usb@vger.kernel.org
L: netdev@vger.kernel.org
+T: git git://petkan@git.code.sf.net/p/pegasus2/git
W: http://pegasus2.sourceforge.net/
S: Maintained
F: drivers/net/usb/pegasus.*
@@ -8380,9 +8381,10 @@ S: Supported
F: drivers/usb/class/usblp.c
USB RTL8150 DRIVER
-M: Petko Manolov <petkan@users.sourceforge.net>
+M: Petko Manolov <petkan@nucleusys.com>
L: linux-usb@vger.kernel.org
L: netdev@vger.kernel.org
+T: git git://petkan@git.code.sf.net/p/pegasus2/git
W: http://pegasus2.sourceforge.net/
S: Maintained
F: drivers/net/usb/rtl8150.c
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 73051d1..501db20 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2005 Petko Manolov (petkan@users.sourceforge.net)
+ * Copyright (c) 1999-2013 Petko Manolov (petkan@nucleusys.com)
*
* 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
@@ -26,6 +26,9 @@
* v0.5.1 ethtool support added
* v0.5.5 rx socket buffers are in a pool and the their allocation
* is out of the interrupt routine.
+ * ...
+ * v0.9.1 simplified [get|set]_register(s), async update registers
+ * logic revisited, receive skb_pool removed.
*/
#include <linux/sched.h>
@@ -45,8 +48,8 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.6.14 (2006/09/27)"
-#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
+#define DRIVER_VERSION "v0.9.3 (2013/04/09)"
+#define DRIVER_AUTHOR "Petko Manolov <petkan@nucleusys.com>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
static const char driver_name[] = "pegasus";
@@ -108,299 +111,154 @@ MODULE_PARM_DESC(msg_level, "Override default message level");
MODULE_DEVICE_TABLE(usb, pegasus_ids);
static const struct net_device_ops pegasus_netdev_ops;
-static int update_eth_regs_async(pegasus_t *);
-/* Aargh!!! I _really_ hate such tweaks */
-static void ctrl_callback(struct urb *urb)
+static void async_ctrl_callback(struct urb *urb)
{
- pegasus_t *pegasus = urb->context;
+ struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
int status = urb->status;
- if (!pegasus)
- return;
-
- switch (status) {
- case 0:
- if (pegasus->flags & ETH_REGS_CHANGE) {
- pegasus->flags &= ~ETH_REGS_CHANGE;
- pegasus->flags |= ETH_REGS_CHANGED;
- update_eth_regs_async(pegasus);
- return;
- }
- break;
- case -EINPROGRESS:
- return;
- case -ENOENT:
- break;
- default:
- if (net_ratelimit())
- netif_dbg(pegasus, drv, pegasus->net,
- "%s, status %d\n", __func__, status);
- break;
- }
- pegasus->flags &= ~ETH_REGS_CHANGED;
- wake_up(&pegasus->ctrl_wait);
+ if (status < 0)
+ dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status);
+ kfree(req);
+ usb_free_urb(urb);
}
-static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
+static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data)
{
int ret;
- char *buffer;
- DECLARE_WAITQUEUE(wait, current);
-
- buffer = kmalloc(size, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- add_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
- while (pegasus->flags & ETH_REGS_CHANGED)
- schedule();
- remove_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_RUNNING);
-
- pegasus->dr.bRequestType = PEGASUS_REQT_READ;
- pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS;
- pegasus->dr.wValue = cpu_to_le16(0);
- pegasus->dr.wIndex = cpu_to_le16(indx);
- pegasus->dr.wLength = cpu_to_le16(size);
- pegasus->ctrl_urb->transfer_buffer_length = size;
-
- usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
- usb_rcvctrlpipe(pegasus->usb, 0),
- (char *) &pegasus->dr,
- buffer, size, ctrl_callback, pegasus);
-
- add_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
-
- /* using ATOMIC, we'd never wake up if we slept */
- if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- set_current_state(TASK_RUNNING);
- if (ret == -ENODEV)
- netif_device_detach(pegasus->net);
- if (net_ratelimit())
- netif_err(pegasus, drv, pegasus->net,
- "%s, status %d\n", __func__, ret);
- goto out;
- }
-
- schedule();
-out:
- remove_wait_queue(&pegasus->ctrl_wait, &wait);
- memcpy(data, buffer, size);
- kfree(buffer);
+ ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
+ PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
+ indx, data, size, 1000);
+ if (ret < 0)
+ netif_dbg(pegasus, drv, pegasus->net,
+ "%s returned %d\n", __func__, ret);
return ret;
}
-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
+static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data)
{
int ret;
- char *buffer;
- DECLARE_WAITQUEUE(wait, current);
-
- buffer = kmemdup(data, size, GFP_KERNEL);
- if (!buffer) {
- netif_warn(pegasus, drv, pegasus->net,
- "out of memory in %s\n", __func__);
- return -ENOMEM;
- }
-
- add_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
- while (pegasus->flags & ETH_REGS_CHANGED)
- schedule();
- remove_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_RUNNING);
-
- pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
- pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
- pegasus->dr.wValue = cpu_to_le16(0);
- pegasus->dr.wIndex = cpu_to_le16(indx);
- pegasus->dr.wLength = cpu_to_le16(size);
- pegasus->ctrl_urb->transfer_buffer_length = size;
-
- usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
- usb_sndctrlpipe(pegasus->usb, 0),
- (char *) &pegasus->dr,
- buffer, size, ctrl_callback, pegasus);
-
- add_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
-
- if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- if (ret == -ENODEV)
- netif_device_detach(pegasus->net);
- netif_err(pegasus, drv, pegasus->net,
- "%s, status %d\n", __func__, ret);
- goto out;
- }
-
- schedule();
-out:
- remove_wait_queue(&pegasus->ctrl_wait, &wait);
- kfree(buffer);
+ ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
+ PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
+ indx, data, size, 100);
+ if (ret < 0)
+ netif_dbg(pegasus, drv, pegasus->net,
+ "%s returned %d\n", __func__, ret);
return ret;
}
-static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
+static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
{
int ret;
- char *tmp;
- DECLARE_WAITQUEUE(wait, current);
-
- tmp = kmemdup(&data, 1, GFP_KERNEL);
- if (!tmp) {
- netif_warn(pegasus, drv, pegasus->net,
- "out of memory in %s\n", __func__);
- return -ENOMEM;
- }
- add_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
- while (pegasus->flags & ETH_REGS_CHANGED)
- schedule();
- remove_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_RUNNING);
-
- pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
- pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
- pegasus->dr.wValue = cpu_to_le16(data);
- pegasus->dr.wIndex = cpu_to_le16(indx);
- pegasus->dr.wLength = cpu_to_le16(1);
- pegasus->ctrl_urb->transfer_buffer_length = 1;
-
- usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
- usb_sndctrlpipe(pegasus->usb, 0),
- (char *) &pegasus->dr,
- tmp, 1, ctrl_callback, pegasus);
-
- add_wait_queue(&pegasus->ctrl_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
-
- if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- if (ret == -ENODEV)
- netif_device_detach(pegasus->net);
- if (net_ratelimit())
- netif_err(pegasus, drv, pegasus->net,
- "%s, status %d\n", __func__, ret);
- goto out;
- }
-
- schedule();
-out:
- remove_wait_queue(&pegasus->ctrl_wait, &wait);
- kfree(tmp);
+ ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
+ PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
+ indx, &data, 1, 1000);
+ if (ret < 0)
+ netif_dbg(pegasus, drv, pegasus->net,
+ "%s returned %d\n", __func__, ret);
return ret;
}
-static int update_eth_regs_async(pegasus_t *pegasus)
+static int update_eth_regs_async(pegasus_t * pegasus)
{
- int ret;
+ int ret = -ENOMEM;
+ struct urb *async_urb;
+ struct usb_ctrlrequest *req;
- pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
- pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
- pegasus->dr.wValue = cpu_to_le16(0);
- pegasus->dr.wIndex = cpu_to_le16(EthCtrl0);
- pegasus->dr.wLength = cpu_to_le16(3);
- pegasus->ctrl_urb->transfer_buffer_length = 3;
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+ if (req == NULL)
+ return ret;
- usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
- usb_sndctrlpipe(pegasus->usb, 0),
- (char *) &pegasus->dr,
- pegasus->eth_regs, 3, ctrl_callback, pegasus);
+ if ((async_urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+ kfree(req);
+ return ret;
+ }
+ req->bRequestType = PEGASUS_REQT_WRITE;
+ req->bRequest = PEGASUS_REQ_SET_REGS;
+ req->wValue = cpu_to_le16(0);
+ req->wIndex = cpu_to_le16(EthCtrl0);
+ req->wLength = cpu_to_le16(3);
+
+ usb_fill_control_urb(async_urb, pegasus->usb,
+ usb_sndctrlpipe(pegasus->usb, 0), (void *)req,
+ pegasus->eth_regs, 3, async_ctrl_callback, req);
- if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+ if ((ret = usb_submit_urb(async_urb, GFP_ATOMIC))) {
if (ret == -ENODEV)
netif_device_detach(pegasus->net);
netif_err(pegasus, drv, pegasus->net,
- "%s, status %d\n", __func__, ret);
+ "%s returned %d\n", __func__, ret);
}
-
return ret;
}
-/* Returns 0 on success, error on failure */
-static int read_mii_word(pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd)
+static int __mii_op(pegasus_t * p, __u8 phy, __u8 indx, __u16 * regd, __u8 cmd)
{
int i;
__u8 data[4] = { phy, 0, 0, indx };
__le16 regdi;
- int ret;
+ int ret = -ETIMEDOUT;
- set_register(pegasus, PhyCtrl, 0);
- set_registers(pegasus, PhyAddr, sizeof(data), data);
- set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+ if (cmd & PHY_WRITE) {
+ __le16 *t = (__le16 *) & data[1];
+ *t = cpu_to_le16(*regd);
+ }
+ set_register(p, PhyCtrl, 0);
+ set_registers(p, PhyAddr, sizeof(data), data);
+ set_register(p, PhyCtrl, (indx | cmd));
for (i = 0; i < REG_TIMEOUT; i++) {
- ret = get_registers(pegasus, PhyCtrl, 1, data);
- if (ret == -ESHUTDOWN)
+ ret = get_registers(p, PhyCtrl, 1, data);
+ if (ret < 0)
goto fail;
if (data[0] & PHY_DONE)
break;
}
-
if (i >= REG_TIMEOUT)
goto fail;
-
- ret = get_registers(pegasus, PhyData, 2, ®di);
- *regd = le16_to_cpu(regdi);
+ if (cmd & PHY_READ) {
+ ret = get_registers(p, PhyData, 2, ®di);
+ *regd = le16_to_cpu(regdi);
+ return ret;
+ }
+ return 0;
+fail:
+ netif_dbg(p, drv, p->net, "%s failed\n", __func__);
return ret;
+}
-fail:
- netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__);
+/* Returns non-negative int on success, error on failure */
+static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
+{
+ return __mii_op(pegasus, phy, indx, regd, PHY_READ);
+}
- return ret;
+/* Returns zero on success, error on failure */
+static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
+{
+ return __mii_op(pegasus, phy, indx, regd, PHY_WRITE);
}
static int mdio_read(struct net_device *dev, int phy_id, int loc)
{
pegasus_t *pegasus = netdev_priv(dev);
- u16 res;
+ __u16 res;
read_mii_word(pegasus, phy_id, loc, &res);
return (int)res;
}
-static int write_mii_word(pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd)
-{
- int i;
- __u8 data[4] = { phy, 0, 0, indx };
- int ret;
-
- data[1] = (u8) regd;
- data[2] = (u8) (regd >> 8);
- set_register(pegasus, PhyCtrl, 0);
- set_registers(pegasus, PhyAddr, sizeof(data), data);
- set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
- for (i = 0; i < REG_TIMEOUT; i++) {
- ret = get_registers(pegasus, PhyCtrl, 1, data);
- if (ret == -ESHUTDOWN)
- goto fail;
- if (data[0] & PHY_DONE)
- break;
- }
-
- if (i >= REG_TIMEOUT)
- goto fail;
-
- return ret;
-
-fail:
- netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__);
- return -ETIMEDOUT;
-}
-
static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
{
pegasus_t *pegasus = netdev_priv(dev);
- write_mii_word(pegasus, phy_id, loc, val);
+ write_mii_word(pegasus, phy_id, loc, (__u16 *) & val);
}
-static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
+static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
{
int i;
__u8 tmp;
@@ -420,18 +278,16 @@ static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
}
if (i >= REG_TIMEOUT)
goto fail;
-
ret = get_registers(pegasus, EpromData, 2, &retdatai);
*retdata = le16_to_cpu(retdatai);
return ret;
-
fail:
netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__);
return -ETIMEDOUT;
}
#ifdef PEGASUS_WRITE_EEPROM
-static inline void enable_eprom_write(pegasus_t *pegasus)
+static inline void enable_eprom_write(pegasus_t * pegasus)
{
__u8 tmp;
int ret;
@@ -440,7 +296,7 @@ static inline void enable_eprom_write(pegasus_t *pegasus)
set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
}
-static inline void disable_eprom_write(pegasus_t *pegasus)
+static inline void disable_eprom_write(pegasus_t * pegasus)
{
__u8 tmp;
int ret;
@@ -450,7 +306,7 @@ static inline void disable_eprom_write(pegasus_t *pegasus)
set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
}
-static int write_eprom_word(pegasus_t *pegasus, __u8 index, __u16 data)
+static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
{
int i;
__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
@@ -473,16 +329,14 @@ static int write_eprom_word(pegasus_t *pegasus, __u8 index, __u16 data)
disable_eprom_write(pegasus);
if (i >= REG_TIMEOUT)
goto fail;
-
return ret;
-
fail:
netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__);
return -ETIMEDOUT;
}
-#endif /* PEGASUS_WRITE_EEPROM */
+#endif /* PEGASUS_WRITE_EEPROM */
-static inline void get_node_id(pegasus_t *pegasus, __u8 *id)
+static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
{
int i;
__u16 w16;
@@ -493,7 +347,7 @@ static inline void get_node_id(pegasus_t *pegasus, __u8 *id)
}
}
-static void set_ethernet_addr(pegasus_t *pegasus)
+static void set_ethernet_addr(pegasus_t * pegasus)
{
__u8 node_id[6];
@@ -506,7 +360,7 @@ static void set_ethernet_addr(pegasus_t *pegasus)
memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id));
}
-static inline int reset_mac(pegasus_t *pegasus)
+static inline int reset_mac(pegasus_t * pegasus)
{
__u8 data = 0x8;
int i;
@@ -528,7 +382,6 @@ static inline int reset_mac(pegasus_t *pegasus)
}
if (i == REG_TIMEOUT)
return -ETIMEDOUT;
-
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
set_register(pegasus, Gpio0, 0x24);
@@ -537,18 +390,17 @@ static inline int reset_mac(pegasus_t *pegasus)
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
__u16 auxmode;
read_mii_word(pegasus, 3, 0x1b, &auxmode);
- write_mii_word(pegasus, 3, 0x1b, auxmode | 4);
+ auxmode |= 4;
+ write_mii_word(pegasus, 3, 0x1b, &auxmode);
}
-
return 0;
}
-static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
+static void enable_net_traffic(struct net_device *dev, struct usb_device *usb)
{
__u16 linkpart;
__u8 data[4];
pegasus_t *pegasus = netdev_priv(dev);
- int ret;
read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
data[0] = 0xc9;
@@ -562,62 +414,16 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
data[2] = loopback ? 0x09 : 0x01;
memcpy(pegasus->eth_regs, data, sizeof(data));
- ret = set_registers(pegasus, EthCtrl0, 3, data);
+ set_registers(pegasus, EthCtrl0, 3, data);
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS2 ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
- u16 auxmode;
+ __u16 auxmode;
read_mii_word(pegasus, 0, 0x1b, &auxmode);
- write_mii_word(pegasus, 0, 0x1b, auxmode | 4);
+ auxmode |= 4;
+ write_mii_word(pegasus, 0, 0x1b, &auxmode);
}
-
- return ret;
-}
-
-static void fill_skb_pool(pegasus_t *pegasus)
-{
- int i;
-
- for (i = 0; i < RX_SKBS; i++) {
- if (pegasus->rx_pool[i])
- continue;
- pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2);
- /*
- ** we give up if the allocation fail. the tasklet will be
- ** rescheduled again anyway...
- */
- if (pegasus->rx_pool[i] == NULL)
- return;
- skb_reserve(pegasus->rx_pool[i], 2);
- }
-}
-
-static void free_skb_pool(pegasus_t *pegasus)
-{
- int i;
-
- for (i = 0; i < RX_SKBS; i++) {
- if (pegasus->rx_pool[i]) {
- dev_kfree_skb(pegasus->rx_pool[i]);
- pegasus->rx_pool[i] = NULL;
- }
- }
-}
-
-static inline struct sk_buff *pull_skb(pegasus_t * pegasus)
-{
- int i;
- struct sk_buff *skb;
-
- for (i = 0; i < RX_SKBS; i++) {
- if (likely(pegasus->rx_pool[i] != NULL)) {
- skb = pegasus->rx_pool[i];
- pegasus->rx_pool[i] = NULL;
- return skb;
- }
- }
- return NULL;
}
static void read_bulk_callback(struct urb *urb)
@@ -643,7 +449,7 @@ static void read_bulk_callback(struct urb *urb)
netif_dbg(pegasus, rx_err, net, "reset MAC\n");
pegasus->flags &= ~PEGASUS_RX_BUSY;
break;
- case -EPIPE: /* stall, or disconnect from TT */
+ case -EPIPE: /* stall, or disconnect from TT */
/* FIXME schedule work to clear the halt */
netif_warn(pegasus, rx_err, net, "no rx stall recovery\n");
return;
@@ -665,16 +471,16 @@ static void read_bulk_callback(struct urb *urb)
netif_dbg(pegasus, rx_err, net,
"RX packet error %x\n", rx_status);
pegasus->stats.rx_errors++;
- if (rx_status & 0x06) /* long or runt */
+ if (rx_status & 0x06) /* long or runt */
pegasus->stats.rx_length_errors++;
if (rx_status & 0x08)
pegasus->stats.rx_crc_errors++;
- if (rx_status & 0x10) /* extra bits */
+ if (rx_status & 0x10) /* extra bits */
pegasus->stats.rx_frame_errors++;
goto goon;
}
if (pegasus->chip == 0x8513) {
- pkt_len = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
+ pkt_len = le32_to_cpu(*(__le32 *) urb->transfer_buffer);
pkt_len &= 0x0fff;
pegasus->rx_skb->data += 2;
} else {
@@ -683,14 +489,12 @@ static void read_bulk_callback(struct urb *urb)
pkt_len &= 0xfff;
pkt_len -= 8;
}
-
/*
* If the packet is unreasonably long, quietly drop it rather than
* kernel panicing by calling skb_put.
*/
if (pkt_len > PEGASUS_MTU)
goto goon;
-
/*
* at this point we are sure pegasus->rx_skb != NULL
* so we go ahead and pass up the packet.
@@ -704,10 +508,8 @@ static void read_bulk_callback(struct urb *urb)
if (pegasus->flags & PEGASUS_UNPLUG)
return;
- spin_lock(&pegasus->rx_pool_lock);
- pegasus->rx_skb = pull_skb(pegasus);
- spin_unlock(&pegasus->rx_pool_lock);
-
+ pegasus->rx_skb = __netdev_alloc_skb_ip_align(pegasus->net,
+ PEGASUS_MTU, GFP_ATOMIC);
if (pegasus->rx_skb == NULL)
goto tl_sched;
goon:
@@ -724,9 +526,7 @@ goon:
} else {
pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
}
-
return;
-
tl_sched:
tasklet_schedule(&pegasus->rx_tl);
}
@@ -734,24 +534,22 @@ tl_sched:
static void rx_fixup(unsigned long data)
{
pegasus_t *pegasus;
- unsigned long flags;
int status;
pegasus = (pegasus_t *) data;
if (pegasus->flags & PEGASUS_UNPLUG)
return;
-
- spin_lock_irqsave(&pegasus->rx_pool_lock, flags);
- fill_skb_pool(pegasus);
if (pegasus->flags & PEGASUS_RX_URB_FAIL)
if (pegasus->rx_skb)
goto try_again;
if (pegasus->rx_skb == NULL)
- pegasus->rx_skb = pull_skb(pegasus);
+ pegasus->rx_skb = __netdev_alloc_skb_ip_align(pegasus->net,
+ PEGASUS_MTU,
+ GFP_ATOMIC);
if (pegasus->rx_skb == NULL) {
netif_warn(pegasus, rx_err, pegasus->net, "low on memory\n");
tasklet_schedule(&pegasus->rx_tl);
- goto done;
+ return;
}
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
@@ -767,8 +565,6 @@ try_again:
} else {
pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
}
-done:
- spin_unlock_irqrestore(&pegasus->rx_pool_lock, flags);
}
static void write_bulk_callback(struct urb *urb)
@@ -779,12 +575,9 @@ static void write_bulk_callback(struct urb *urb)
if (!pegasus)
return;
-
net = pegasus->net;
-
if (!netif_device_present(net) || !netif_running(net))
return;
-
switch (status) {
case -EPIPE:
/* FIXME schedule_work() to clear the tx halt */
@@ -802,8 +595,7 @@ static void write_bulk_callback(struct urb *urb)
case 0:
break;
}
-
- net->trans_start = jiffies; /* prevent tx timeout */
+ net->trans_start = jiffies; /* prevent tx timeout */
netif_wake_queue(net);
}
@@ -816,7 +608,6 @@ static void intr_callback(struct urb *urb)
if (!pegasus)
return;
net = pegasus->net;
-
switch (status) {
case 0:
break;
@@ -830,13 +621,12 @@ static void intr_callback(struct urb *urb)
*/
netif_dbg(pegasus, timer, net, "intr status %d\n", status);
}
-
if (urb->actual_length >= 6) {
u8 *d = urb->transfer_buffer;
/* byte 0 == tx_status1, reg 2B */
- if (d[0] & (TX_UNDERRUN|EXCESSIVE_COL
- |LATE_COL|JABBER_TIMEOUT)) {
+ if (d[0] & (TX_UNDERRUN | EXCESSIVE_COL
+ | LATE_COL | JABBER_TIMEOUT)) {
pegasus->stats.tx_errors++;
if (d[0] & TX_UNDERRUN)
pegasus->stats.tx_fifo_errors++;
@@ -854,7 +644,6 @@ static void intr_callback(struct urb *urb)
/* bytes 3-4 == rx_lostpkt, reg 2E/2F */
pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
}
-
res = usb_submit_urb(urb, GFP_ATOMIC);
if (res == -ENODEV)
netif_device_detach(pegasus->net);
@@ -872,7 +661,7 @@ static void pegasus_tx_timeout(struct net_device *net)
}
static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb,
- struct net_device *net)
+ struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3;
@@ -890,10 +679,10 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb,
if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
netif_warn(pegasus, tx_err, net, "fail tx, %d\n", res);
switch (res) {
- case -EPIPE: /* stall, or disconnect from TT */
+ case -EPIPE: /* stall, or disconnect from TT */
/* cleanup should already have been scheduled */
break;
- case -ENODEV: /* disconnect() upcoming */
+ case -ENODEV: /* disconnect() upcoming */
case -EPERM:
netif_device_detach(pegasus->net);
break;
@@ -915,14 +704,14 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
return &((pegasus_t *) netdev_priv(dev))->stats;
}
-static inline void disable_net_traffic(pegasus_t *pegasus)
+static inline void disable_net_traffic(pegasus_t * pegasus)
{
__le16 tmp = cpu_to_le16(0);
set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp);
}
-static inline void get_interrupt_interval(pegasus_t *pegasus)
+static inline void get_interrupt_interval(pegasus_t * pegasus)
{
u16 data;
u8 interval;
@@ -935,7 +724,7 @@ static inline void get_interrupt_interval(pegasus_t *pegasus)
"intr interval changed from %ums to %ums\n",
interval, 0x80);
interval = 0x80;
- data = (data & 0x00FF) | ((u16)interval << 8);
+ data = (data & 0x00FF) | ((u16) interval << 8);
#ifdef PEGASUS_WRITE_EEPROM
write_eprom_word(pegasus, 4, data);
#endif
@@ -951,71 +740,58 @@ static void set_carrier(struct net_device *net)
if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
return;
-
if (tmp & BMSR_LSTATUS)
netif_carrier_on(net);
else
netif_carrier_off(net);
}
-static void free_all_urbs(pegasus_t *pegasus)
+static void free_all_urbs(pegasus_t * pegasus)
{
usb_free_urb(pegasus->intr_urb);
usb_free_urb(pegasus->tx_urb);
usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
}
-static void unlink_all_urbs(pegasus_t *pegasus)
+static void unlink_all_urbs(pegasus_t * pegasus)
{
usb_kill_urb(pegasus->intr_urb);
usb_kill_urb(pegasus->tx_urb);
usb_kill_urb(pegasus->rx_urb);
- usb_kill_urb(pegasus->ctrl_urb);
}
-static int alloc_urbs(pegasus_t *pegasus)
+static int alloc_urbs(pegasus_t * pegasus)
{
- pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!pegasus->ctrl_urb)
- return 0;
pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->rx_urb) {
- usb_free_urb(pegasus->ctrl_urb);
return 0;
}
pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->tx_urb) {
usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
return 0;
}
pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->intr_urb) {
usb_free_urb(pegasus->tx_urb);
usb_free_urb(pegasus->rx_urb);
- usb_free_urb(pegasus->ctrl_urb);
return 0;
}
-
return 1;
}
static int pegasus_open(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- int res;
+ int res = -ENOMEM;
if (pegasus->rx_skb == NULL)
- pegasus->rx_skb = pull_skb(pegasus);
- /*
- ** Note: no point to free the pool. it is empty :-)
- */
+ pegasus->rx_skb = __netdev_alloc_skb_ip_align(pegasus->net,
+ PEGASUS_MTU,
+ GFP_KERNEL);
if (!pegasus->rx_skb)
- return -ENOMEM;
-
+ goto exit;
res = set_registers(pegasus, EthID, 6, net->dev_addr);
-
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_skb->data, PEGASUS_MTU + 8,
@@ -1026,7 +802,6 @@ static int pegasus_open(struct net_device *net)
netif_dbg(pegasus, ifup, net, "failed rx_urb, %d\n", res);
goto exit;
}
-
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof(pegasus->intr_buff),
@@ -1038,18 +813,9 @@ static int pegasus_open(struct net_device *net)
usb_kill_urb(pegasus->rx_urb);
goto exit;
}
- if ((res = enable_net_traffic(net, pegasus->usb))) {
- netif_dbg(pegasus, ifup, net,
- "can't enable_net_traffic() - %d\n", res);
- res = -EIO;
- usb_kill_urb(pegasus->rx_urb);
- usb_kill_urb(pegasus->intr_urb);
- free_skb_pool(pegasus);
- goto exit;
- }
+ enable_net_traffic(net, pegasus->usb);
set_carrier(net);
netif_start_queue(net);
- netif_dbg(pegasus, ifup, net, "open\n");
res = 0;
exit:
return res;
@@ -1081,25 +847,22 @@ static void pegasus_get_drvinfo(struct net_device *dev,
/* also handles three patterns of some kind in hardware */
#define WOL_SUPPORTED (WAKE_MAGIC|WAKE_PHY)
-static void
-pegasus_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+static void pegasus_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- pegasus_t *pegasus = netdev_priv(dev);
+ pegasus_t *pegasus = netdev_priv(dev);
wol->supported = WAKE_MAGIC | WAKE_PHY;
wol->wolopts = pegasus->wolopts;
}
-static int
-pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+static int pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- pegasus_t *pegasus = netdev_priv(dev);
- u8 reg78 = 0x04;
- int ret;
+ pegasus_t *pegasus = netdev_priv(dev);
+ u8 reg78 = 0x04;
+ int r;
if (wol->wolopts & ~WOL_SUPPORTED)
return -EINVAL;
-
if (wol->wolopts & WAKE_MAGIC)
reg78 |= 0x80;
if (wol->wolopts & WAKE_PHY)
@@ -1111,11 +874,10 @@ pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
pegasus->eth_regs[0] &= ~0x10;
pegasus->wolopts = wol->wolopts;
- ret = set_register(pegasus, WakeupControl, reg78);
- if (!ret)
- ret = device_set_wakeup_enable(&pegasus->usb->dev,
- wol->wolopts);
- return ret;
+ r = set_register(pegasus, WakeupControl, reg78);
+ if (!r)
+ r = device_set_wakeup_enable(&pegasus->usb->dev, wol->wolopts);
+ return r;
}
static inline void pegasus_reset_wol(struct net_device *dev)
@@ -1123,7 +885,7 @@ static inline void pegasus_reset_wol(struct net_device *dev)
struct ethtool_wolinfo wol;
memset(&wol, 0, sizeof wol);
- (void) pegasus_set_wol(dev, &wol);
+ (void)pegasus_set_wol(dev, &wol);
}
static int
@@ -1133,6 +895,7 @@ pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
pegasus = netdev_priv(dev);
mii_ethtool_gset(&pegasus->mii, ecmd);
+
return 0;
}
@@ -1140,30 +903,35 @@ static int
pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
pegasus_t *pegasus = netdev_priv(dev);
+
return mii_ethtool_sset(&pegasus->mii, ecmd);
}
static int pegasus_nway_reset(struct net_device *dev)
{
pegasus_t *pegasus = netdev_priv(dev);
+
return mii_nway_restart(&pegasus->mii);
}
static u32 pegasus_get_link(struct net_device *dev)
{
pegasus_t *pegasus = netdev_priv(dev);
+
return mii_link_ok(&pegasus->mii);
}
static u32 pegasus_get_msglevel(struct net_device *dev)
{
pegasus_t *pegasus = netdev_priv(dev);
+
return pegasus->msg_enable;
}
static void pegasus_set_msglevel(struct net_device *dev, u32 v)
{
pegasus_t *pegasus = netdev_priv(dev);
+
pegasus->msg_enable = v;
}
@@ -1181,7 +949,7 @@ static const struct ethtool_ops ops = {
static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
- __u16 *data = (__u16 *) &rq->ifr_ifru;
+ __u16 *data = (__u16 *) & rq->ifr_ifru;
pegasus_t *pegasus = netdev_priv(net);
int res;
@@ -1195,7 +963,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
case SIOCDEVPRIVATE + 2:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]);
+ write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, &data[2]);
res = 0;
break;
default:
@@ -1218,15 +986,12 @@ static void pegasus_set_multicast(struct net_device *net)
} else {
pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
+ netif_dbg(pegasus, link, net, "general mode\n");
}
-
- pegasus->ctrl_urb->status = 0;
-
- pegasus->flags |= ETH_REGS_CHANGE;
- ctrl_callback(pegasus->ctrl_urb);
+ update_eth_regs_async(pegasus);
}
-static __u8 mii_phy_probe(pegasus_t *pegasus)
+static __u8 mii_phy_probe(pegasus_t * pegasus)
{
int i;
__u16 tmp;
@@ -1238,11 +1003,10 @@ static __u8 mii_phy_probe(pegasus_t *pegasus)
else
return i;
}
-
return 0xff;
}
-static inline void setup_pegasus_II(pegasus_t *pegasus)
+static inline void setup_pegasus_II(pegasus_t * pegasus)
{
__u8 data = 0xa5;
@@ -1253,26 +1017,21 @@ static inline void setup_pegasus_II(pegasus_t *pegasus)
set_register(pegasus, Reg7b, 0);
else
set_register(pegasus, Reg7b, 2);
-
set_register(pegasus, 0x83, data);
get_registers(pegasus, 0x83, 1, &data);
-
if (data == 0xa5)
pegasus->chip = 0x8513;
else
pegasus->chip = 0;
-
set_register(pegasus, 0x80, 0xc0);
set_register(pegasus, 0x83, 0xff);
set_register(pegasus, 0x84, 0x01);
-
if (pegasus->features & HAS_HOME_PNA && mii_mode)
set_register(pegasus, Reg81, 6);
else
set_register(pegasus, Reg81, 2);
}
-
static int pegasus_count;
static struct workqueue_struct *pegasus_workqueue;
#define CARRIER_CHECK_DELAY (2 * HZ)
@@ -1281,10 +1040,9 @@ static void check_carrier(struct work_struct *work)
{
pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work);
set_carrier(pegasus->net);
- if (!(pegasus->flags & PEGASUS_UNPLUG)) {
+ if (!(pegasus->flags & PEGASUS_UNPLUG))
queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
- CARRIER_CHECK_DELAY);
- }
+ CARRIER_CHECK_DELAY);
}
static int pegasus_blacklisted(struct usb_device *udev)
@@ -1299,11 +1057,11 @@ static int pegasus_blacklisted(struct usb_device *udev)
(udd->bDeviceClass == USB_CLASS_WIRELESS_CONTROLLER) &&
(udd->bDeviceProtocol == 1))
return 1;
-
return 0;
}
-/* we rely on probe() and remove() being serialized so we
+/*
+ * we rely on probe() and remove() being serialized so we
* don't need extra locking on pegasus_count.
*/
static void pegasus_dec_workqueue(void)
@@ -1340,14 +1098,13 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus = netdev_priv(net);
pegasus->dev_index = dev_index;
- init_waitqueue_head(&pegasus->ctrl_wait);
if (!alloc_urbs(pegasus)) {
dev_err(&intf->dev, "can't allocate %s\n", "urbs");
goto out1;
}
- tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
+ tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long)pegasus);
INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
@@ -1355,7 +1112,6 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->usb = dev;
pegasus->net = net;
-
net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
net->netdev_ops = &pegasus_netdev_ops;
SET_ETHTOOL_OPS(net, &ops);
@@ -1364,9 +1120,9 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->mii.mdio_write = mdio_write;
pegasus->mii.phy_id_mask = 0x1f;
pegasus->mii.reg_num_mask = 0x1f;
- spin_lock_init(&pegasus->rx_pool_lock);
pegasus->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV
- | NETIF_MSG_PROBE | NETIF_MSG_LINK);
+ | NETIF_MSG_PROBE
+ | NETIF_MSG_LINK);
pegasus->features = usb_dev_id[dev_index].private;
get_interrupt_interval(pegasus);
@@ -1376,7 +1132,6 @@ static int pegasus_probe(struct usb_interface *intf,
goto out2;
}
set_ethernet_addr(pegasus);
- fill_skb_pool(pegasus);
if (pegasus->features & PEGASUS_II) {
dev_info(&intf->dev, "setup Pegasus II specific registers\n");
setup_pegasus_II(pegasus);
@@ -1394,17 +1149,12 @@ static int pegasus_probe(struct usb_interface *intf,
if (res)
goto out3;
queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
- CARRIER_CHECK_DELAY);
-
- dev_info(&intf->dev, "%s, %s, %pM\n",
- net->name,
- usb_dev_id[dev_index].name,
- net->dev_addr);
+ CARRIER_CHECK_DELAY);
+ dev_info(&intf->dev, "%s, %s: %pM\n", net->name,
+ usb_dev_id[dev_index].name, net->dev_addr);
return 0;
-
out3:
usb_set_intfdata(intf, NULL);
- free_skb_pool(pegasus);
out2:
free_all_urbs(pegasus);
out1:
@@ -1429,7 +1179,6 @@ static void pegasus_disconnect(struct usb_interface *intf)
unregister_netdev(pegasus->net);
unlink_all_urbs(pegasus);
free_all_urbs(pegasus);
- free_skb_pool(pegasus);
if (pegasus->rx_skb != NULL) {
dev_kfree_skb(pegasus->rx_skb);
pegasus->rx_skb = NULL;
@@ -1466,21 +1215,21 @@ static int pegasus_resume(struct usb_interface *intf)
intr_callback(pegasus->intr_urb);
}
queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
- CARRIER_CHECK_DELAY);
+ CARRIER_CHECK_DELAY);
return 0;
}
static const struct net_device_ops pegasus_netdev_ops = {
- .ndo_open = pegasus_open,
- .ndo_stop = pegasus_close,
- .ndo_do_ioctl = pegasus_ioctl,
- .ndo_start_xmit = pegasus_start_xmit,
- .ndo_set_rx_mode = pegasus_set_multicast,
- .ndo_get_stats = pegasus_netdev_stats,
- .ndo_tx_timeout = pegasus_tx_timeout,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
+ .ndo_open = pegasus_open,
+ .ndo_stop = pegasus_close,
+ .ndo_do_ioctl = pegasus_ioctl,
+ .ndo_start_xmit = pegasus_start_xmit,
+ .ndo_set_rx_mode = pegasus_set_multicast,
+ .ndo_get_stats = pegasus_netdev_stats,
+ .ndo_tx_timeout = pegasus_tx_timeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
};
static struct usb_driver pegasus_driver = {
@@ -1500,7 +1249,7 @@ static void __init parse_id(char *id)
if ((token = strsep(&id, ":")) != NULL)
name = token;
- /* name now points to a null terminated string*/
+ /* name now points to a null terminated string */
if ((token = strsep(&id, ":")) != NULL)
vendor_id = simple_strtoul(token, NULL, 16);
if ((token = strsep(&id, ":")) != NULL)
@@ -1514,7 +1263,7 @@ static void __init parse_id(char *id)
if (device_id > 0x10000 || device_id == 0)
return;
- for (i = 0; usb_dev_id[i].name; i++);
+ for (i = 0; usb_dev_id[i].name; i++) ;
usb_dev_id[i].name = name;
usb_dev_id[i].vendor = vendor_id;
usb_dev_id[i].device = device_id;
diff --git a/drivers/net/usb/pegasus.h b/drivers/net/usb/pegasus.h
index 65b78b3..809e560 100644
--- a/drivers/net/usb/pegasus.h
+++ b/drivers/net/usb/pegasus.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Petko Manolov - Petkan (petkan@users.sourceforge.net)
+ * Copyright (c) 1999-2013 Petko Manolov - Petkan (petkan@nucleusys.com)
*
* 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
@@ -34,8 +34,6 @@
#define CTRL_URB_SLEEP 0x00000020
#define PEGASUS_UNPLUG 0x00000040
#define PEGASUS_RX_URB_FAIL 0x00000080
-#define ETH_REGS_CHANGE 0x40000000
-#define ETH_REGS_CHANGED 0x80000000
#define RX_MULTICAST 2
#define RX_PROMISCUOUS 4
@@ -96,12 +94,8 @@ typedef struct pegasus {
int intr_interval;
struct tasklet_struct rx_tl;
struct delayed_work carrier_check;
- struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
- struct sk_buff *rx_pool[RX_SKBS];
+ struct urb *rx_urb, *tx_urb, *intr_urb;
struct sk_buff *rx_skb;
- struct usb_ctrlrequest dr;
- wait_queue_head_t ctrl_wait;
- spinlock_t rx_pool_lock;
int chip;
unsigned char intr_buff[8];
__u8 tx_buff[PEGASUS_MTU];
^ permalink raw reply related
* Re: [PATCH repost for-3.9] pci: avoid work_on_cpu for nested SRIOV probes
From: Tejun Heo @ 2013-04-11 19:04 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Or Gerlitz, Ming Lei, Greg Kroah-Hartman, David Miller,
Roland Dreier, netdev, Yan Burman, Jack Morgenstein,
Bjorn Helgaas, linux-pci
In-Reply-To: <20130411185853.GE23301@redhat.com>
Hey,
On Thu, Apr 11, 2013 at 09:58:54PM +0300, Michael S. Tsirkin wrote:
> > Hmm... how about adding a work_on_cpu_nested() which takes @subclass
> > argument? Wouldn't that be much cleaner?
> >
> > Thanks.
>
> Is that 3.9 material though?
Why wouldn't it be? It's actually safer as it doesn't change any
logic. It's just updating lockdep annotation, which is what's needed
here anyway.
Thanks.
--
tejun
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox