* Re: Libertas related kernel crash
From: Daniel Mack @ 2009-11-10 6:54 UTC (permalink / raw)
To: Dan Williams; +Cc: netdev, libertas-dev, Michael Hirsch, linux-kernel
In-Reply-To: <1257835893.15493.37.camel@localhost.localdomain>
On Mon, Nov 09, 2009 at 10:51:33PM -0800, Dan Williams wrote:
> On Mon, 2009-11-09 at 16:53 +0100, Daniel Mack wrote:
> > On Thu, Nov 05, 2009 at 01:05:49PM +0100, Daniel Mack wrote:
> > > On an ARM (PXA300) embdedded platform with a libertas chip connected via
> > > SDIO, we happen to see the kernel Ooops below once in a while.
> > >
> > > Any pointer on where to dig?
> >
> > Some more input on this. Oopses similar to the one below are likely
> > triggered when switching from Ad-hoc to managed mode multiple times in a
> > row, and something seems corrupt the memory badly. I've searched for the
> > obvious (double frees, out-of-bound writes etc), but I couldn't find
> > anything yet. It is, however, related to the wireless core and/or the
> > libertas driver.
>
> Probably just libertas. Any chance you can enable debugging options
> (either in libertas, or in the kernel allocator) to help narrow down the
> issue?
Sure. I already enabled DEBUG_VM, but that didn't spit out anything
before it crashes. Which other debug flags would you recommend to set?
Daniel
^ permalink raw reply
* Re: Libertas related kernel crash
From: Dan Williams @ 2009-11-10 6:51 UTC (permalink / raw)
To: Daniel Mack; +Cc: netdev, libertas-dev, Michael Hirsch, linux-kernel
In-Reply-To: <20091109155354.GC14091@buzzloop.caiaq.de>
On Mon, 2009-11-09 at 16:53 +0100, Daniel Mack wrote:
> On Thu, Nov 05, 2009 at 01:05:49PM +0100, Daniel Mack wrote:
> > On an ARM (PXA300) embdedded platform with a libertas chip connected via
> > SDIO, we happen to see the kernel Ooops below once in a while.
> >
> > Any pointer on where to dig?
>
> Some more input on this. Oopses similar to the one below are likely
> triggered when switching from Ad-hoc to managed mode multiple times in a
> row, and something seems corrupt the memory badly. I've searched for the
> obvious (double frees, out-of-bound writes etc), but I couldn't find
> anything yet. It is, however, related to the wireless core and/or the
> libertas driver.
Probably just libertas. Any chance you can enable debugging options
(either in libertas, or in the kernel allocator) to help narrow down the
issue?
Dan
> Any ideas, anyone?
>
> Daniel
>
>
> > [ 2659.715112] Unable to handle kernel NULL pointer dereference at virtual address 00000001
> > [ 2659.723164] pgd = c5ca8000
> > [ 2659.725846] [00000001] *pgd=a5cbc031, *pte=00000000, *ppte=00000000
> > [ 2659.732062] Internal error: Oops: 13 [#4]
> > [ 2659.736041] last sysfs file: /sys/devices/platform/pxa2xx-mci.0/mmc_host/mmc0/mmc0:0001/mmc0:0001:1/net/wlan0/address
> > [ 2659.746573] Modules linked in: eeti_ts libertas_sdio pxamci ds2760_battery w1_ds2760 wire
> > [ 2659.754698] CPU: 0 Tainted: G D (2.6.32-rc6 #1)
> > [ 2659.760255] PC is at kmem_cache_alloc+0x30/0x90
> > [ 2659.764774] LR is at inet_bind_bucket_create+0x18/0x5c
> > [ 2659.769876] pc : [<c00a28d8>] lr : [<c02a4b24>] psr: 20000093
> > [ 2659.769887] sp : c5c27d88 ip : c78ae4a0 fp : 00006e49
> > [ 2659.781279] r10: 00008928 r9 : c04fcfac r8 : c0532148
> > [ 2659.786466] r7 : 00000020 r6 : 00000020 r5 : 60000013 r4 : 00000001
> > [ 2659.792945] r3 : 00000000 r2 : c78ae4a0 r1 : 00000020 r0 : c04d42e4
> > [ 2659.799427] Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
> > [ 2659.806602] Control: 0000397f Table: a5ca8018 DAC: 00000015
> > [ 2659.812304] Process p0-renderer (pid: 1527, stack limit = 0xc5c26278)
> > [ 2659.818697] Stack: (0xc5c27d88 to 0xc5c28000)
> > [ 2659.823029] 7d80: c5cc5300 c5cb1000 c5c18800 c78ae4a0 00008928 00008928
> > [ 2659.831155] 7da0: 00000001 c02a4b24 c2388c2e 00000000 c7eb6200 c02a4c8c c02a4200 c2388c2d
> > [ 2659.839287] 7dc0: c04fcfac 00000000 0000ee48 00008000 fb0ca8c0 c7eb6200 c04fcfac 00000000
> > [ 2659.847412] 7de0: 000038e5 fb0ca8c0 fb0ca8c0 c7eb6200 00000000 c02a4e28 c02a40e4 00000000
> > [ 2659.855543] 7e00: 00000000 00000000 00000000 c02b99d4 00000001 00000000 c5c27f08 00000000
> > [ 2659.863669] 7e20: c5c7b500 000005a8 00000000 00000000 000200da c5c7b500 c0069a74 c5c27e3c
> > [ 2659.871802] 7e40: c5c27e3c c0049fdc be96a8fc c0275d70 c5c27e88 00000006 00000005 00000001
> > [ 2659.879933] 7e60: 00000000 00000000 00000000 fb0ca8c0 1d0ca8c0 00000000 00000000 00000000
> > [ 2659.888057] 7e80: 00000000 00000000 00000000 00000000 00000006 38e50000 00000000 c7ff6e00
> > [ 2659.896183] 7ea0: 000063f8 c5c27f08 00000010 c7eb6200 c5c27f08 c00440c4 c5c26000 c76cd2c0
> > [ 2659.904314] 7ec0: 00000802 c02c4f70 0000c1ff 00000001 00000000 00000000 00000000 00045108
> > [ 2659.912441] 7ee0: 00000010 c76cd2c0 00045108 00000010 c5c27f08 c00440c4 c5c26000 40343800
> > [ 2659.920573] 7f00: 00044440 c0276888 38e50002 fb0ca8c0 00000000 00000000 000063f8 00000000
> > [ 2659.928698] 7f20: 00000000 be96a858 c5c27f48 000450c0 000000c5 c00440c4 c5c26000 40343800
> > [ 2659.936829] 7f40: 00044440 c00a9864 000063f8 00000000 00000005 c047c1ff 00000001 00000000
> > [ 2659.944952] 7f60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000003
> > [ 2659.953078] 7f80: 00000000 c7b5aa00 00000000 00000000 00000000 00046cb8 00045108 40370ef8
> > [ 2659.961203] 7fa0: 0000011b c0043f40 00046cb8 00045108 0000000a 00045108 00000010 0000001c
> > [ 2659.969328] 7fc0: 00046cb8 00045108 40370ef8 0000011b 00000000 00043178 40343800 00044440
> > [ 2659.977451] 7fe0: 40371050 be96a968 4035b3c8 40790638 60000010 0000000a 00000000 00000000
> > [ 2659.985599] [<c00a28d8>] (kmem_cache_alloc+0x30/0x90) from [<c02a4b24>] (inet_bind_bucket_create+0x18/0x5c)
> > [ 2659.995296] [<c02a4b24>] (inet_bind_bucket_create+0x18/0x5c) from [<c02a4c8c>] (__inet_hash_connect+0x124/0x280)
> > [ 2660.005415] [<c02a4c8c>] (__inet_hash_connect+0x124/0x280) from [<c02a4e28>] (inet_hash_connect+0x40/0x50)
> > [ 2660.015034] [<c02a4e28>] (inet_hash_connect+0x40/0x50) from [<c02b99d4>] (tcp_v4_connect+0x2a8/0x420)
> > [ 2660.024211] [<c02b99d4>] (tcp_v4_connect+0x2a8/0x420) from [<c02c4f70>] (inet_stream_connect+0xac/0x26c)
> > [ 2660.033653] [<c02c4f70>] (inet_stream_connect+0xac/0x26c) from [<c0276888>] (sys_connect+0x6c/0x90)
> > [ 2660.042662] [<c0276888>] (sys_connect+0x6c/0x90) from [<c0043f40>] (ret_fast_syscall+0x0/0x28)
> > [ 2660.051228] Code: e5904080 e5907090 e3540000 1590308c (17943103) [ 2660.057440] ---[ end trace 416b23b4578ffa42 ]---
> > [ 2660.062021] Kernel panic - not syncing: Fatal exception in interrupt
> > [ 2660.068400] [<c00486cc>] (unwind_backtrace+0x0/0xdc) from [<c0351758>] (panic+0x34/0x120)
> > [ 2660.076555] [<c0351758>] (panic+0x34/0x120) from [<c004758c>] (die+0x14c/0x178)
> > [ 2660.083823] [<c004758c>] (die+0x14c/0x178) from [<c0049900>] (__do_kernel_fault+0x68/0x80)
> > [ 2660.092060] [<c0049900>] (__do_kernel_fault+0x68/0x80) from [<c004b678>] (do_alignment+0x59c/0x700)
> > [ 2660.101067] [<c004b678>] (do_alignment+0x59c/0x700) from [<c00432c8>] (do_DataAbort+0x34/0x94)
> > [ 2660.109649] [<c00432c8>] (do_DataAbort+0x34/0x94) from [<c0043acc>] (__dabt_svc+0x4c/0x60)
> > [ 2660.117874] Exception stack(0xc5c27d40 to 0xc5c27d88)
> > [ 2660.122898] 7d40: c04d42e4 00000020 c78ae4a0 00000000 00000001 60000013 00000020 00000020
> > [ 2660.131046] 7d60: c0532148 c04fcfac 00008928 00006e49 c78ae4a0 c5c27d88 c02a4b24 c00a28d8
> > [ 2660.139189] 7d80: 20000093 ffffffff
> > [ 2660.142673] [<c0043acc>] (__dabt_svc+0x4c/0x60) from [<c00a28d8>] (kmem_cache_alloc+0x30/0x90)
> > [ 2660.151265] [<c00a28d8>] (kmem_cache_alloc+0x30/0x90) from [<c02a4b24>] (inet_bind_bucket_create+0x18/0x5c)
> > [ 2660.160998] [<c02a4b24>] (inet_bind_bucket_create+0x18/0x5c) from [<c02a4c8c>] (__inet_hash_connect+0x124/0x280)
> > [ 2660.171148] [<c02a4c8c>] (__inet_hash_connect+0x124/0x280) from [<c02a4e28>] (inet_hash_connect+0x40/0x50)
> > [ 2660.180780] [<c02a4e28>] (inet_hash_connect+0x40/0x50) from [<c02b99d4>] (tcp_v4_connect+0x2a8/0x420)
> > [ 2660.189971] [<c02b99d4>] (tcp_v4_connect+0x2a8/0x420) from [<c02c4f70>] (inet_stream_connect+0xac/0x26c)
> > [ 2660.199424] [<c02c4f70>] (inet_stream_connect+0xac/0x26c) from [<c0276888>] (sys_connect+0x6c/0x90)
> > [ 2660.208443] [<c0276888>] (sys_connect+0x6c/0x90) from [<c0043f40>] (ret_fast_syscall+0x0/0x28)
> >
>
> _______________________________________________
> libertas-dev mailing list
> libertas-dev@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev
^ permalink raw reply
* Re: [Patch] net: fix incorrect counting in __scm_destroy()
From: Eric Dumazet @ 2009-11-10 6:33 UTC (permalink / raw)
To: Cong Wang; +Cc: David Miller, linux-kernel, netdev
In-Reply-To: <4AF90461.5090800@redhat.com>
Cong Wang a écrit :
>
> Yes, this even happens after commit f8d570a47.
>
> But after doing a bisect, we found another hrtimer patch fixes this
> problem, so it's not a bug of __scm_destroy().
>
> Sorry for the noise.
>
Thanks for the explanation !
^ permalink raw reply
* Re: [Patch] net: fix incorrect counting in __scm_destroy()
From: Cong Wang @ 2009-11-10 6:12 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, linux-kernel, netdev
In-Reply-To: <20091104.044116.37320720.davem@davemloft.net>
David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Wed, 04 Nov 2009 11:29:05 +0100
>
>> Given we kfree(fpl) at the end of loop, we cannot recursively call
>> __scm_destroy() on same fpl, it would be a bug anyway ?
>>
>> So you probably need something better, like testing fpl->list being
>> not re-included in current->scm_work_list before kfree() it
>
> I can't even see what the problem is.
>
> The code is designed such that the ->count only matters for
> the top level.
>
> If we recursively fput() and get back here, we'll see that
> there is someone higher in the call chain already running
> the fput() loop and we'll just list_add_tail().
>
> The inner while() loop will make sure we process such
> entries once we get back to the top level and exit the
> for() loop.
>
> Amerigo, please show us the problematic code path where the counts go
> wrong and this causes problems.
Hi, all.
Thanks for your replies.
I met a soft lockup around this code on ia64, something like:
[<a0000001006394e0>] unix_gc+0x240/0x760
sp=e0000260f002fd70 bsp=e0000260f0029560
[<a000000100634500>] unix_release_sock+0x440/0x460
sp=e0000260f002fdb0 bsp=e0000260f0029508
[<a000000100634560>] unix_release+0x40/0x60
sp=e0000260f002fdb0 bsp=e0000260f00294e8
[<a00000010051fba0>] sock_release+0x80/0x1c0
sp=e0000260f002fdb0 bsp=e0000260f00294c0
[<a00000010051fd60>] sock_close+0x80/0xa0
sp=e0000260f002fdc0 bsp=e0000260f0029498
[<a000000100172280>] __fput+0x1a0/0x420
sp=e0000260f002fdc0 bsp=e0000260f0029458
[<a000000100172540>] fput+0x40/0x60
sp=e0000260f002fdc0 bsp=e0000260f0029438
[<a000000100534a30>] __scm_destroy+0x130/0x1e0
sp=e0000260f002fdc0 bsp=e0000260f0029410
[<a000000100636370>] unix_destruct_fds+0x70/0xa0
sp=e0000260f002fdd0 bsp=e0000260f00293e8
[<a00000010052da30>] __kfree_skb+0x1f0/0x320
sp=e0000260f002fe00 bsp=e0000260f00293c0
[<a00000010052dbf0>] kfree_skb+0x90/0xc0
sp=e0000260f002fe00 bsp=e0000260f00293a0
[<a000000100634420>] unix_release_sock+0x360/0x460
sp=e0000260f002fe00 bsp=e0000260f0029348
[<a000000100634560>] unix_release+0x40/0x60
sp=e0000260f002fe00 bsp=e0000260f0029328
[<a00000010051fba0>] sock_release+0x80/0x1c0
sp=e0000260f002fe00 bsp=e0000260f0029300
[<a00000010051fd60>] sock_close+0x80/0xa0
sp=e0000260f002fe10 bsp=e0000260f00292d8
[<a000000100172280>] __fput+0x1a0/0x420
sp=e0000260f002fe10 bsp=e0000260f0029298
[<a000000100172540>] fput+0x40/0x60
sp=e0000260f002fe10 bsp=e0000260f0029278
Yes, this even happens after commit f8d570a47.
But after doing a bisect, we found another hrtimer patch fixes this
problem, so it's not a bug of __scm_destroy().
Sorry for the noise.
Thanks.
^ permalink raw reply
* Re: [net-next-2.6 PATCH v5 3/5 RFC] TCPCT part1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS, functions
From: Ilpo Järvinen @ 2009-11-10 5:31 UTC (permalink / raw)
To: William Allen Simpson; +Cc: Linux Kernel Network Developers
In-Reply-To: <4AF84458.9070000@gmail.com>
On Mon, 9 Nov 2009, William Allen Simpson wrote:
> Define sysctl (tcp_cookie_size) to turn on and off the cookie option
> default globally, instead of a compiled configuration option.
>
> Define per socket option (TCP_COOKIE_TRANSACTIONS) for setting constant
> data values, retrieving variable cookie values, and other facilities.
I guess most of the cookie stuff have nothing to do with the next,
please make them separate:
> Redefine two TCP header functions to accept TCP header pointer.
> When subtracting, return signed int to allow error checking.
Convert the users here, not in the fifth patch to avoid noise in the large
fifth patch.
And, I read more that fifth patch... seriously, please consider now to
apply _all_ the coding style changes that have been brought to your
attention by multiple people (you should know them now but for some reason
again you choose to resent without complying -- I guess on purpose) into
all upcoming patches you submit.
--
i.
^ permalink raw reply
* Re: [net-next-2.6 PATCH v5 5/5 RFC] TCPCT part1e: initial SYN exchange with SYNACK data
From: Ilpo Järvinen @ 2009-11-10 5:05 UTC (permalink / raw)
To: William Allen Simpson
Cc: Linux Kernel Network Developers, Eric Dumazet, Joe Perches
In-Reply-To: <4AF84BF3.5020302@gmail.com>
On Mon, 9 Nov 2009, William Allen Simpson wrote:
> This is a significantly revised implementation of an earlier (year-old)
> patch that no longer applies cleanly, with permission of the original
> author (Adam Langley). That patch was previously reviewed:
>
> http://thread.gmane.org/gmane.linux.network/102586
>
> The principle difference is using a TCP option to carry the cookie nonce,
> instead of a user configured offset in the data. This is more flexible and
> less subject to user configuration error. Such a cookie option has been
> suggested for many years, and is also useful without SYN data, allowing
> several related concepts to use the same extension option.
>
> "Re: SYN floods (was: does history repeat itself?)", September 9, 1996.
> http://www.merit.net/mail.archives/nanog/1996-09/msg00235.html
>
> "Re: what a new TCP header might look like", May 12, 1998.
> ftp://ftp.isi.edu/end2end/end2end-interest-1998.mail
>
> Data structures are carefully composed to require minimal additions.
> For example, the struct tcp_options_received cookie_plus variable fits
> between existing 16-bit and 8-bit variables, requiring no additional
> space (taking alignment into consideration). There are no additions to
> tcp_request_sock, and only 1 pointer in tcp_sock.
>
> Allocations have been rearranged to avoid requiring GFP_ATOMIC, with
> only one unavoidable exception in tcp_create_openreq_child(), where the
> tcp_sock itself is created GFP_ATOMIC.
>
> These functions will also be used in subsequent patches that implement
> additional features.
>
> Requires:
> TCPCT part 1a: add request_values parameter for sending SYNACK
> TCPCT part 1b: TCP_MSS_DEFAULT, TCP_MSS_DESIRED
> TCPCT part 1c: sysctl_tcp_cookie_size, socket option
> TCP_COOKIE_TRANSACTIONS, functions
> TCPCT part 1d: generate Responder Cookie
>
> Signed-off-by: William.Allen.Simpson@gmail.com
> ---
> include/linux/tcp.h | 29 ++++-
> include/net/tcp.h | 72 +++++++++++++
> net/ipv4/syncookies.c | 5 +-
> net/ipv4/tcp.c | 127 ++++++++++++++++++++++-
> net/ipv4/tcp_input.c | 86 +++++++++++++--
> net/ipv4/tcp_ipv4.c | 69 ++++++++++++-
> net/ipv4/tcp_minisocks.c | 59 ++++++++---
> net/ipv4/tcp_output.c | 255
> +++++++++++++++++++++++++++++++++++++++++-----
> net/ipv6/syncookies.c | 5 +-
> net/ipv6/tcp_ipv6.c | 65 +++++++++++-
> 10 files changed, 701 insertions(+), 71 deletions(-)
>
One general comment. ...This particular patch still has lots of noise
which does not belong to the context of this change. ...Please try to
minimize. Eg., if you don't like sizeof(struct tcphdr) but prefer
sizeof(*th), you certainly don't have to do it in this particular patch!
...Also some comment changes which certainly are not mandatory nor even
related.
--
i.
^ permalink raw reply
* [PATCH] RDMA/addr: Use appropriate locking with for_each_netdev()
From: Eric Dumazet @ 2009-11-10 4:27 UTC (permalink / raw)
To: David S. Miller
Cc: Linux Netdev List, Roland Dreier, Sean Hefty, Hal Rosenstock
for_each_netdev() should be used with RTNL or dev_base_lock held,
or risk a crash.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/infiniband/core/addr.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index bd07803..5ca0b2c 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -131,6 +131,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
+ read_lock(&dev_base_lock);
for_each_netdev(&init_net, dev) {
if (ipv6_chk_addr(&init_net,
&((struct sockaddr_in6 *) addr)->sin6_addr,
@@ -139,6 +140,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
break;
}
}
+ read_unlock(&dev_base_lock);
break;
#endif
}
@@ -391,15 +393,17 @@ static int addr_resolve_local(struct sockaddr *src_in,
{
struct in6_addr *a;
+ read_lock(&dev_base_lock);
for_each_netdev(&init_net, dev)
if (ipv6_chk_addr(&init_net,
&((struct sockaddr_in6 *) dst_in)->sin6_addr,
dev, 1))
break;
- if (!dev)
+ if (!dev) {
+ read_unlock(&dev_base_lock);
return -EADDRNOTAVAIL;
-
+ }
a = &((struct sockaddr_in6 *) src_in)->sin6_addr;
if (ipv6_addr_any(a)) {
@@ -416,6 +420,7 @@ static int addr_resolve_local(struct sockaddr *src_in,
if (!ret)
memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
}
+ read_unlock(&dev_base_lock);
break;
}
#endif
^ permalink raw reply related
* [PATCH net-next-2.6] parisc: led: Use for_each_netdev_rcu()
From: Eric Dumazet @ 2009-11-10 4:07 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List
Use for_each_netdev_rcu() and dont lock dev_base_lock anymore
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/parisc/led.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 9581d36..79caf1c 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -352,11 +352,9 @@ static __inline__ int led_get_net_activity(void)
rx_total = tx_total = 0;
- /* we are running as a workqueue task, so locking dev_base
- * for reading should be OK */
- read_lock(&dev_base_lock);
+ /* we are running as a workqueue task, so we can use an RCU lookup */
rcu_read_lock();
- for_each_netdev(&init_net, dev) {
+ for_each_netdev_rcu(&init_net, dev) {
const struct net_device_stats *stats;
struct in_device *in_dev = __in_dev_get_rcu(dev);
if (!in_dev || !in_dev->ifa_list)
@@ -368,7 +366,6 @@ static __inline__ int led_get_net_activity(void)
tx_total += stats->tx_packets;
}
rcu_read_unlock();
- read_unlock(&dev_base_lock);
retval = 0;
^ permalink raw reply related
* [PATCH] niu.c: Use correct length in strncmp
From: Joe Perches @ 2009-11-10 4:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
Untested, no hardware
Signed-off-by: Joe Perches <joe@perches.com>
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index d6c7ac6..d0f96bc 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -8144,7 +8144,7 @@ static void __devinit niu_vpd_parse_version(struct niu *np)
int i;
for (i = 0; i < len - 5; i++) {
- if (!strncmp(s + i, "FCode ", 5))
+ if (!strncmp(s + i, "FCode ", 6))
break;
}
if (i >= len - 5)
^ permalink raw reply related
* Bigger tool with less efforts
From: Sadie Wilcox @ 2009-11-10 4:48 UTC (permalink / raw)
To: netdev
Drive her wet and crazy http://kwyru.gimpyfhaycs.com/
^ permalink raw reply
* Re: [PATCH] check the return value of ndo_select_queue()
From: Eric Dumazet @ 2009-11-10 3:43 UTC (permalink / raw)
To: xiaosuo; +Cc: David S. Miller, netdev
In-Reply-To: <4AF8C4E9.3030907@gmail.com>
Changli Gao a écrit :
> check the return value of ndo_select_queue()
>
> Check the return value of ndo_select_queue(). If the value isn't smaller
> than the real_num_tx_queues, print a warning message, and reset it to zero.
>
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* Re: [PATCHv9 3/3] vhost_net: a kernel-level virtio server
From: Rusty Russell @ 2009-11-10 3:19 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm,
hpa, gregory.haskins, s.hetze, Daniel Walker, Eric Dumazet
In-Reply-To: <20091109172230.GD4724@redhat.com>
One fix:
vhost: fix TUN=m VHOST_NET=y
drivers/built-in.o: In function `get_tun_socket':
net.c:(.text+0x15436e): undefined reference to `tun_get_socket'
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
drivers/vhost/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -1,6 +1,6 @@
config VHOST_NET
tristate "Host kernel accelerator for virtio net (EXPERIMENTAL)"
- depends on NET && EVENTFD && EXPERIMENTAL
+ depends on NET && EVENTFD && TUN && EXPERIMENTAL
---help---
This kernel module can be loaded in host kernel to accelerate
guest networking with virtio_net. Not to be confused with virtio_net
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* (unknown)
From: MR SMITH @ 2009-11-10 2:53 UTC (permalink / raw)
Do you need A
Business or a Personal Loan? Then your Answer is here. We
offer
loan at 3% as well with a flexible plan.and customer's convinient terms*
We offer the following;
Hard Money Loans
Business Loan.
Debt Consolidation Loan.
Personal Loan.
Business Expansion Loan.
And Lots more..........
If interested in any of the following, contact us now on
happy_smithloanfirm@hotmail.com for more infor..
REGARDS
^ permalink raw reply
* Re: [PATCHv9 3/3] vhost_net: a kernel-level virtio server
From: Rusty Russell @ 2009-11-10 2:48 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm,
hpa, gregory.haskins, s.hetze, Daniel Walker, Eric Dumazet
In-Reply-To: <20091109172230.GD4724@redhat.com>
On Tue, 10 Nov 2009 03:52:30 am Michael S. Tsirkin wrote:
> What it is: vhost net is a character device that can be used to reduce
> the number of system calls involved in virtio networking.
> Existing virtio net code is used in the guest without modification.
Thanks, applied. Will be in tomorrow's linux-next.
Cheers,
Rusty.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH] check the return value of ndo_select_queue()
From: Changli Gao @ 2009-11-10 1:42 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, xiaosuo, Eric Dumazet
check the return value of ndo_select_queue()
Check the return value of ndo_select_queue(). If the value isn't smaller
than the real_num_tx_queues, print a warning message, and reset it to zero.
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
net/core/dev.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index b8f74cf..be081a5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1791,13 +1791,25 @@ EXPORT_SYMBOL(skb_tx_hash);
static struct netdev_queue *dev_pick_tx(struct net_device *dev,
struct sk_buff *skb)
{
- const struct net_device_ops *ops = dev->netdev_ops;
- u16 queue_index = 0;
-
- if (ops->ndo_select_queue)
- queue_index = ops->ndo_select_queue(dev, skb);
- else if (dev->real_num_tx_queues > 1)
+ u16 queue_index;
+ u16 (*ndo_select_queue)(struct net_device*, struct sk_buff*);
+ unsigned int real_num_tx_queues = dev->real_num_tx_queues;
+
+ if (real_num_tx_queues == 1) {
+ queue_index = 0;
+ } else if ((ndo_select_queue = dev->netdev_ops->ndo_select_queue)) {
+ queue_index = ndo_select_queue(dev, skb);
+ if (unlikely(queue_index >= real_num_tx_queues)) {
+ if (net_ratelimit())
+ WARN(1, "%s selects TX queue %d, "
+ "but real number of TX queues is %d\n",
+ dev->name, queue_index,
+ real_num_tx_queues);
+ queue_index = 0;
+ }
+ } else {
queue_index = skb_tx_hash(dev, skb);
+ }
skb_set_queue_mapping(skb, queue_index);
return netdev_get_tx_queue(dev, queue_index);
^ permalink raw reply related
* Re: [PATCHv8 3/3] vhost_net: a kernel-level virtio server
From: Rusty Russell @ 2009-11-10 1:08 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm,
hpa, gregory.haskins, s.hetze, Daniel Walker, Eric Dumazet
In-Reply-To: <8f53421d0911082310n1f5f487ew8c2c03d2e1d7ca5c@mail.gmail.com>
On Mon, 9 Nov 2009 05:40:32 pm Michael S. Tsirkin wrote:
> On Mon, Nov 9, 2009 at 8:17 AM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> > There's something about the 'acked' which rubs me the wrong way.
> > "enabled_features" is perhaps a better term than "acked_features"; "acked"
> > seems more a user point-of-view, "enabled" seems more driver POV?
>
> Hmm. Are you happy with the ioctl name? If yes I think being consistent
> with that is important.
I think in my original comments I noted that I preferred GET / SET, rather
than GET/ACK.
> > Actually, this looks wrong to me:
> >
> > + case VHOST_SET_VRING_BASE:
> > ...
> > + vq->avail_idx = vq->last_avail_idx = s.num;
> >
> > The last_avail_idx is part of the state of the driver. It needs to be saved
> > and restored over susp/resume.
>
>
> Exactly. That's what VHOST_GET/SET_VRING_BASE does. avail_idx is just a
> cached value for notify on empty, so what this does is clear the value.
Ah, you actually refresh it every time anyway. Hmm, could you do my poor
brain a favor and either just get_user it in vhost_trigger_irq(), or call
it 'cached_avail_idx' or something?
> > The only reason it's not in the ring itself
> > is because I figured the other side doesn't need to see it (which is true, but
> > missed debugging opportunities as well as man-in-the-middle issues like this
> > one). I had a patch which put this field at the end of the ring, I might
> > resurrect it to avoid this problem. This is backwards compatible with all
> > implementations. See patch at end.
>
> Yes, I remember that patch. There seems to be little point though, at
> this stage.
Well, it avoids this ioctl, by exposing all the state. We may well need it
later, to expand the ring in other ways.
> > I would drop avail_idx altogether: get_user is basically free, and simplifies
> > a lot. As most state is in the ring, all you need is an ioctl to save/restore
> > the last_avail_idx.
>
> avail_idx is there for notify on empty: I had this thought that it's
> better to leave the avail cache line alone when we are triggering
> interrupt to avoid bouncing it around if guest is updating it meanwhile
> on another CPU, and I think my testing showed that it helped
> performance, but could be a mistake. You don't believe this can help?
I believe it could help, but this is YA case where it would have been nice to
have a dumb basic patch and this as a patch on top. But I am going to ask
you to re-run that measurement, see if it stacks up (because it's an
interesting lesson if it does..)
Thanks!
Rusty.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Possible bug: SO_TIMESTAMPING 2.6.30+
From: Marcus D. Leech @ 2009-11-10 0:40 UTC (permalink / raw)
To: netdev
I've searched both the LKML archives, and the patchsets for kernels
since 2.6.30 to see if
this problem has been observed.
I have an Ethernet driver that supports hardware timestamping, and it
has been working
swimmingly well for several months using the SO_TIMESTAMPING
infrastructure that
Patrick Ohly put in the kernel starting around 2.6.30.
What I've discovered, that really causes me to pull my hair out, is that
packets that are
either AF_INET6 or AF_PACKET, *are not* getting Tx (transmit)
timestamps. Diving into
the driver, I've discovered that the sk_buffs associated with these
packets *dont* have
the appropriate skb_tx state in the skb:
shtx = skb_tx(skb);
if (shtx->hardware)
{
/* Do the timestamping thing */
}
Now the puzzling thing is that the socket that originates these packets
has SO_TIMESTAMPING
turned on, and was created as an AF_INET6 socket, but carries both V4
and V6 traffic. The
V4 traffic skbs have shtx->hardware true appropriately, but the
V6 traffic doesn't. Using
Wireshark, I can clearly see the V6 packets leaving the interface, so
it's not like they're
getting routed somewhere else, and debugging in the driver *clearly*
shows that V4 packets
have shtx->hardware, while the V6 ones (from the SAME SOCKET) do not.
I know that Patrick Ohly has essentially moved on from doing the
SO_TIMESTAMPING stuff, so
who's maintaining it now?
When I look at the V6 udp code, it seems to call the same udp_sendmsg()
function that V4
uses, which appears to support Tx timestamping the way it should.
Any clues anyone?
^ permalink raw reply
* [PATCH 2/2] au1000-eth: convert to platform_driver model
From: Florian Fainelli @ 2009-11-10 0:13 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
This patch converts the au1000-eth driver to become a full
platform-driver as it ought to be. We now pass PHY-speficic
configurations through platform_data but for compatibility
the driver still assumes the default settings (search for PHY1 on
MAC0) when no platform_data is passed. Tested on my MTX-1 board.
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index ce6f1ac..6d5a2cb 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -55,6 +55,7 @@
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/phy.h>
+#include <linux/platform_device.h>
#include <asm/cpu.h>
#include <asm/mipsregs.h>
@@ -63,6 +64,7 @@
#include <asm/processor.h>
#include <au1000.h>
+#include <au1xxx_eth.h>
#include <prom.h>
#include "au1000_eth.h"
@@ -112,15 +114,15 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
*
* PHY detection algorithm
*
- * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is
+ * If phy_static_config is undefined, the PHY setup is
* autodetected:
*
* mii_probe() first searches the current MAC's MII bus for a PHY,
- * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is
+ * selecting the first (or last, if phy_search_highest_addr is
* defined) PHY address not already claimed by another netdev.
*
* If nothing was found that way when searching for the 2nd ethernet
- * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then
+ * controller's PHY and phy1_search_mac0 is defined, then
* the first MII bus is searched as well for an unclaimed PHY; this is
* needed in case of a dual-PHY accessible only through the MAC0's MII
* bus.
@@ -129,9 +131,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
* controller is not registered to the network subsystem.
*/
-/* autodetection defaults */
-#undef AU1XXX_PHY_SEARCH_HIGHEST_ADDR
-#define AU1XXX_PHY1_SEARCH_ON_MAC0
+/* autodetection defaults: phy1_search_mac0 */
/* static PHY setup
*
@@ -148,29 +148,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
* specific irq-map
*/
-#if defined(CONFIG_MIPS_BOSPORUS)
-/*
- * Micrel/Kendin 5 port switch attached to MAC0,
- * MAC0 is associated with PHY address 5 (== WAN port)
- * MAC1 is not associated with any PHY, since it's connected directly
- * to the switch.
- * no interrupts are used
- */
-# define AU1XXX_PHY_STATIC_CONFIG
-
-# define AU1XXX_PHY0_ADDR 5
-# define AU1XXX_PHY0_BUSID 0
-# undef AU1XXX_PHY0_IRQ
-
-# undef AU1XXX_PHY1_ADDR
-# undef AU1XXX_PHY1_BUSID
-# undef AU1XXX_PHY1_IRQ
-#endif
-
-#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
-# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
-#endif
-
static void enable_mac(struct net_device *dev, int force_reset)
{
unsigned long flags;
@@ -390,67 +367,54 @@ static int mii_probe (struct net_device *dev)
struct au1000_private *const aup = netdev_priv(dev);
struct phy_device *phydev = NULL;
-#if defined(AU1XXX_PHY_STATIC_CONFIG)
- BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
+ if (aup->phy_static_config) {
+ BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
- if(aup->mac_id == 0) { /* get PHY0 */
-# if defined(AU1XXX_PHY0_ADDR)
- phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus->phy_map[AU1XXX_PHY0_ADDR];
-# else
- printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
- dev->name);
- return 0;
-# endif /* defined(AU1XXX_PHY0_ADDR) */
- } else if (aup->mac_id == 1) { /* get PHY1 */
-# if defined(AU1XXX_PHY1_ADDR)
- phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus->phy_map[AU1XXX_PHY1_ADDR];
-# else
- printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
- dev->name);
+ if (aup->phy_addr)
+ phydev = aup->mii_bus->phy_map[aup->phy_addr];
+ else
+ printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+ dev->name);
return 0;
-# endif /* defined(AU1XXX_PHY1_ADDR) */
- }
-
-#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */
- int phy_addr;
-
- /* find the first (lowest address) PHY on the current MAC's MII bus */
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
- if (aup->mii_bus->phy_map[phy_addr]) {
- phydev = aup->mii_bus->phy_map[phy_addr];
-# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR)
- break; /* break out with first one found */
-# endif
- }
-
-# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0)
- /* try harder to find a PHY */
- if (!phydev && (aup->mac_id == 1)) {
- /* no PHY found, maybe we have a dual PHY? */
- printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, "
- "let's see if it's attached to MAC0...\n");
-
- BUG_ON(!au_macs[0]);
-
- /* find the first (lowest address) non-attached PHY on
- * the MAC0 MII bus */
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- struct phy_device *const tmp_phydev =
- au_macs[0]->mii_bus->phy_map[phy_addr];
-
- if (!tmp_phydev)
- continue; /* no PHY here... */
-
- if (tmp_phydev->attached_dev)
- continue; /* already claimed by MAC0 */
+ } else {
+ int phy_addr;
+
+ /* find the first (lowest address) PHY on the current MAC's MII bus */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+ if (aup->mii_bus->phy_map[phy_addr]) {
+ phydev = aup->mii_bus->phy_map[phy_addr];
+ if (!aup->phy_search_highest_addr)
+ break; /* break out with first one found */
+ }
- phydev = tmp_phydev;
- break; /* found it */
+ if (aup->phy1_search_mac0) {
+ /* try harder to find a PHY */
+ if (!phydev && (aup->mac_id == 1)) {
+ /* no PHY found, maybe we have a dual PHY? */
+ printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, "
+ "let's see if it's attached to MAC0...\n");
+
+ /* find the first (lowest address) non-attached PHY on
+ * the MAC0 MII bus */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+ if (aup->mac_id == 1)
+ break;
+ struct phy_device *const tmp_phydev =
+ aup->mii_bus->phy_map[phy_addr];
+
+ if (!tmp_phydev)
+ continue; /* no PHY here... */
+
+ if (tmp_phydev->attached_dev)
+ continue; /* already claimed by MAC0 */
+
+ phydev = tmp_phydev;
+ break; /* found it */
+ }
+ }
}
}
-# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */
-#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */
if (!phydev) {
printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name);
return -1;
@@ -578,31 +542,6 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
}
}
-static struct {
- u32 base_addr;
- u32 macen_addr;
- int irq;
- struct net_device *dev;
-} iflist[2] = {
-#ifdef CONFIG_SOC_AU1000
- {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT},
- {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT}
-#endif
-#ifdef CONFIG_SOC_AU1100
- {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT}
-#endif
-#ifdef CONFIG_SOC_AU1500
- {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT},
- {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT}
-#endif
-#ifdef CONFIG_SOC_AU1550
- {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT},
- {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT}
-#endif
-};
-
-static int num_ifs;
-
/*
* ethtool operations
*/
@@ -1058,46 +997,59 @@ static const struct net_device_ops au1000_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
};
-static struct net_device * au1000_probe(int port_num)
+static int __devinit au1000_probe(struct platform_device *pdev)
{
static unsigned version_printed = 0;
struct au1000_private *aup = NULL;
+ struct au1000_eth_platform_data *pd;
struct net_device *dev = NULL;
db_dest_t *pDB, *pDBfree;
- char ethaddr[6];
- int irq, i, err;
- u32 base, macen;
+ int irq, i, err = 0;
+ struct resource *base, *macen;
+ DECLARE_MAC_BUF(ethaddr);
+
+ base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!base) {
+ printk(KERN_ERR DRV_NAME ": failed to retrieve base register\n");
+ err = -ENODEV;
+ goto out;
+ }
- if (port_num >= NUM_ETH_INTERFACES)
- return NULL;
+ macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!macen) {
+ printk(KERN_ERR DRV_NAME ": failed to retrieve MAC Enable register\n");
+ err = -ENODEV;
+ goto out;
+ }
- base = CPHYSADDR(iflist[port_num].base_addr );
- macen = CPHYSADDR(iflist[port_num].macen_addr);
- irq = iflist[port_num].irq;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ printk(KERN_ERR DRV_NAME ": failed to retrieve IRQ\n");
+ err = -ENODEV;
+ goto out;
+ }
- if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
- !request_mem_region(macen, 4, "Au1x00 ENET"))
- return NULL;
+ if (!request_mem_region(base->start, resource_size(base), pdev->name)) {
+ printk(KERN_ERR DRV_NAME ": failed to request memory region for base registers\n");
+ err = -ENXIO;
+ goto out;
+ }
- if (version_printed++ == 0)
- printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+ if (!request_mem_region(macen->start, resource_size(macen), pdev->name)) {
+ printk(KERN_ERR DRV_NAME ": failed to request memory region for MAC enable register\n");
+ err = -ENXIO;
+ goto err_request;
+ }
dev = alloc_etherdev(sizeof(struct au1000_private));
if (!dev) {
printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
- return NULL;
+ err = -ENOMEM;
+ goto err_alloc;
}
- if ((err = register_netdev(dev)) != 0) {
- printk(KERN_ERR "%s: Cannot register net device, error %d\n",
- DRV_NAME, err);
- free_netdev(dev);
- return NULL;
- }
-
- printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
- dev->name, base, irq);
-
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ platform_set_drvdata(pdev, dev);
aup = netdev_priv(dev);
spin_lock_init(&aup->lock);
@@ -1108,21 +1060,29 @@ static struct net_device * au1000_probe(int port_num)
(NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, 0);
if (!aup->vaddr) {
- free_netdev(dev);
- release_mem_region( base, MAC_IOSIZE);
- release_mem_region(macen, 4);
- return NULL;
+ printk(KERN_ERR DRV_NAME ": failed to allocate data buffers\n");
+ err = -ENOMEM;
+ goto err_vaddr;
}
/* aup->mac is the base address of the MAC's registers */
- aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
+ aup->mac = (volatile mac_reg_t *)ioremap_nocache(base->start, resource_size(base));
+ if (!aup->mac) {
+ printk(KERN_ERR DRV_NAME ": failed to ioremap MAC registers\n");
+ err = -ENXIO;
+ goto err_remap1;
+ }
- /* Setup some variables for quick register address access */
- aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
- aup->mac_id = port_num;
- au_macs[port_num] = aup;
+ /* Setup some variables for quick register address access */
+ aup->enable = (volatile u32 *)ioremap_nocache(macen->start, resource_size(macen));
+ if (!aup->enable) {
+ printk(KERN_ERR DRV_NAME ": failed to ioremap MAC enable register\n");
+ err = -ENXIO;
+ goto err_remap2;
+ }
+ aup->mac_id = pdev->id;
- if (port_num == 0) {
+ if (pdev->id == 0) {
if (prom_get_ethernet_addr(ethaddr) == 0)
memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
else {
@@ -1132,7 +1092,7 @@ static struct net_device * au1000_probe(int port_num)
}
setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
- } else if (port_num == 1)
+ } else if (pdev->id == 1)
setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
/*
@@ -1140,14 +1100,37 @@ static struct net_device * au1000_probe(int port_num)
* to match those that are printed on their stickers
*/
memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
- dev->dev_addr[5] += port_num;
+ dev->dev_addr[5] += pdev->id;
*aup->enable = 0;
aup->mac_enabled = 0;
+ pd = pdev->dev.platform_data;
+ if (!pd) {
+ printk(KERN_INFO DRV_NAME ": no platform_data passed, PHY search on MAC0\n");
+ aup->phy1_search_mac0 = 1;
+ } else {
+ aup->phy_static_config = pd->phy_static_config;
+ aup->phy_search_highest_addr = pd->phy_search_highest_addr;
+ aup->phy1_search_mac0 = pd->phy1_search_mac0;
+ aup->phy_addr = pd->phy_addr;
+ aup->phy_busid = pd->phy_busid;
+ aup->phy_irq = pd->phy_irq;
+ }
+
+ if (aup->phy_busid && aup->phy_busid > 0) {
+ printk(KERN_ERR DRV_NAME ": MAC0-associated PHY attached 2nd MACs MII"
+ "bus not supported yet\n");
+ err = -ENODEV;
+ goto err_mdiobus_alloc;
+ }
+
aup->mii_bus = mdiobus_alloc();
- if (aup->mii_bus == NULL)
- goto err_out;
+ if (aup->mii_bus == NULL) {
+ printk(KERN_ERR DRV_NAME ": failed to allocate mdiobus structure\n");
+ err = -ENOMEM;
+ goto err_mdiobus_alloc;
+ }
aup->mii_bus->priv = dev;
aup->mii_bus->read = au1000_mdiobus_read;
@@ -1161,23 +1144,19 @@ static struct net_device * au1000_probe(int port_num)
for(i = 0; i < PHY_MAX_ADDR; ++i)
aup->mii_bus->irq[i] = PHY_POLL;
-
/* if known, set corresponding PHY IRQs */
-#if defined(AU1XXX_PHY_STATIC_CONFIG)
-# if defined(AU1XXX_PHY0_IRQ)
- if (AU1XXX_PHY0_BUSID == aup->mac_id)
- aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
-# endif
-# if defined(AU1XXX_PHY1_IRQ)
- if (AU1XXX_PHY1_BUSID == aup->mac_id)
- aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
-# endif
-#endif
- mdiobus_register(aup->mii_bus);
+ if (aup->phy_static_config)
+ if (aup->phy_irq && aup->phy_busid == aup->mac_id)
+ aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq;
+
+ err = mdiobus_register(aup->mii_bus);
+ if (err) {
+ printk(KERN_ERR DRV_NAME " failed to register MDIO bus\n");
+ goto err_mdiobus_reg;
+ }
- if (mii_probe(dev) != 0) {
+ if (mii_probe(dev) != 0)
goto err_out;
- }
pDBfree = NULL;
/* setup the data buffer descriptors and attach a buffer to each one */
@@ -1209,7 +1188,7 @@ static struct net_device * au1000_probe(int port_num)
aup->tx_db_inuse[i] = pDB;
}
- dev->base_addr = base;
+ dev->base_addr = base->start;
dev->irq = irq;
dev->netdev_ops = &au1000_netdev_ops;
SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
@@ -1221,13 +1200,23 @@ static struct net_device * au1000_probe(int port_num)
*/
reset_mac(dev);
- return dev;
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR DRV_NAME "%s: Cannot register net device, aborting.\n",
+ dev->name);
+ goto err_out;
+ }
+
+ printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
+ dev->name, base->start, irq);
+ if (version_printed++ == 0)
+ printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+
+ return 0;
err_out:
- if (aup->mii_bus != NULL) {
+ if (aup->mii_bus != NULL)
mdiobus_unregister(aup->mii_bus);
- mdiobus_free(aup->mii_bus);
- }
/* here we should have a valid dev plus aup-> register addresses
* so we can reset the mac properly.*/
@@ -1241,67 +1230,84 @@ err_out:
if (aup->tx_db_inuse[i])
ReleaseDB(aup, aup->tx_db_inuse[i]);
}
+err_mdiobus_reg:
+ mdiobus_free(aup->mii_bus);
+err_mdiobus_alloc:
+ iounmap(aup->enable);
+err_remap2:
+ iounmap(aup->mac);
+err_remap1:
dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
(void *)aup->vaddr, aup->dma_addr);
- unregister_netdev(dev);
+err_vaddr:
free_netdev(dev);
- release_mem_region( base, MAC_IOSIZE);
- release_mem_region(macen, 4);
- return NULL;
+err_alloc:
+ release_mem_region(macen->start, resource_size(macen));
+err_request:
+ release_mem_region(base->start, resource_size(base));
+out:
+ return err;
}
-/*
- * Setup the base address and interrupt of the Au1xxx ethernet macs
- * based on cpu type and whether the interface is enabled in sys_pinfunc
- * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
- */
-static int __init au1000_init_module(void)
+static int __devexit au1000_remove(struct platform_device *pdev)
{
- int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
- struct net_device *dev;
- int i, found_one = 0;
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct au1000_private *aup = netdev_priv(dev);
+ int i;
+ struct resource *base, *macen;
- num_ifs = NUM_ETH_INTERFACES - ni;
+ platform_set_drvdata(pdev, NULL);
+
+ unregister_netdev(dev);
+ mdiobus_unregister(aup->mii_bus);
+ mdiobus_free(aup->mii_bus);
+
+ for (i = 0; i < NUM_RX_DMA; i++)
+ if (aup->rx_db_inuse[i])
+ ReleaseDB(aup, aup->rx_db_inuse[i]);
+
+ for (i = 0; i < NUM_TX_DMA; i++)
+ if (aup->tx_db_inuse[i])
+ ReleaseDB(aup, aup->tx_db_inuse[i]);
+
+ dma_free_noncoherent(NULL, MAX_BUF_SIZE *
+ (NUM_TX_BUFFS + NUM_RX_BUFFS),
+ (void *)aup->vaddr, aup->dma_addr);
+
+ iounmap(aup->mac);
+ iounmap(aup->enable);
+
+ base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(base->start, resource_size(base));
+
+ macen = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ release_mem_region(macen->start, resource_size(macen));
+
+ free_netdev(dev);
- for(i = 0; i < num_ifs; i++) {
- dev = au1000_probe(i);
- iflist[i].dev = dev;
- if (dev)
- found_one++;
- }
- if (!found_one)
- return -ENODEV;
return 0;
}
-static void __exit au1000_cleanup_module(void)
+static struct platform_driver au1000_eth_driver = {
+ .probe = au1000_probe,
+ .remove = __devexit_p(au1000_remove),
+ .driver = {
+ .name = "au1000-eth",
+ .owner = THIS_MODULE,
+ },
+};
+MODULE_ALIAS("platform:au1000-eth");
+
+
+static int __init au1000_init_module(void)
{
- int i, j;
- struct net_device *dev;
- struct au1000_private *aup;
-
- for (i = 0; i < num_ifs; i++) {
- dev = iflist[i].dev;
- if (dev) {
- aup = netdev_priv(dev);
- unregister_netdev(dev);
- mdiobus_unregister(aup->mii_bus);
- mdiobus_free(aup->mii_bus);
- for (j = 0; j < NUM_RX_DMA; j++)
- if (aup->rx_db_inuse[j])
- ReleaseDB(aup, aup->rx_db_inuse[j]);
- for (j = 0; j < NUM_TX_DMA; j++)
- if (aup->tx_db_inuse[j])
- ReleaseDB(aup, aup->tx_db_inuse[j]);
- dma_free_noncoherent(NULL, MAX_BUF_SIZE *
- (NUM_TX_BUFFS + NUM_RX_BUFFS),
- (void *)aup->vaddr, aup->dma_addr);
- release_mem_region(dev->base_addr, MAC_IOSIZE);
- release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
- free_netdev(dev);
- }
- }
+ return platform_driver_register(&au1000_eth_driver);
+}
+
+static void __exit au1000_exit_module(void)
+{
+ platform_driver_unregister(&au1000_eth_driver);
}
module_init(au1000_init_module);
-module_exit(au1000_cleanup_module);
+module_exit(au1000_exit_module);
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index 824ecd5..f9d29a2 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -108,6 +108,15 @@ struct au1000_private {
struct phy_device *phy_dev;
struct mii_bus *mii_bus;
+ /* PHY configuration */
+ int phy_static_config;
+ int phy_search_highest_addr;
+ int phy1_search_mac0;
+
+ int phy_addr;
+ int phy_busid;
+ int phy_irq;
+
/* These variables are just for quick access to certain regs addresses. */
volatile mac_reg_t *mac; /* mac registers */
volatile u32 *enable; /* address of MAC Enable Register */
^ permalink raw reply related
* [PATCH 1/2] alchemy: add au1000-eth platform device
From: Florian Fainelli @ 2009-11-10 0:13 UTC (permalink / raw)
To: Ralf Baechle, netdev, David Miller; +Cc: linux-mips
(resending per Ralf's request as the patch had some checkpatch errors)
This patch makes the board code register the au1000-eth
platform device. The au1000-eth platform data can be
overriden with the au1xxx_override_eth_cfg function
like it has to be done for the Bosporus board which uses
a different MAC/PHY setup.
Changes from v3:
- declare a static au1000_eth_platform_data structure for bosporus and
initialize it
- remove parenthis and bit shifting on SYS_PF_NI2
Changes from v2:
- declared the au1000-eth second driver instance platform_data
- made the override function generic and pass it the port number too
Changes from v1:
- remove per-board platform.c file
- add an override function to pass custom eth0 platform_data PHY settings
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index 3be14b0..3fbe30c 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -19,6 +19,7 @@
#include <asm/mach-au1x00/au1xxx.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/mach-au1x00/au1xxx_eth.h>
#define PORT(_base, _irq) \
{ \
@@ -326,6 +327,88 @@ static struct platform_device pbdb_smbus_device = {
};
#endif
+/* Macro to help defining the Ethernet MAC resources */
+#define MAC_RES(_base, _enable, _irq) \
+ { \
+ .start = CPHYSADDR(_base), \
+ .end = CPHYSADDR(_base + 0xffff), \
+ .flags = IORESOURCE_MEM, \
+ }, \
+ { \
+ .start = CPHYSADDR(_enable), \
+ .end = CPHYSADDR(_enable + 0x3), \
+ .flags = IORESOURCE_MEM, \
+ }, \
+ { \
+ .start = _irq, \
+ .end = _irq, \
+ .flags = IORESOURCE_IRQ \
+ }
+
+static struct resource au1xxx_eth0_resources[] = {
+#if defined(CONFIG_SOC_AU1000)
+ MAC_RES(AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT),
+#elif defined(CONFIG_SOC_AU1100)
+ MAC_RES(AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT),
+#elif defined(CONFIG_SOC_AU1550)
+ MAC_RES(AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT),
+#elif defined(CONFIG_SOC_AU1500)
+ MAC_RES(AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT),
+#endif
+};
+
+static struct resource au1xxx_eth1_resources[] = {
+#if defined(CONFIG_SOC_AU1000)
+ MAC_RES(AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT),
+#elif defined(CONFIG_SOC_AU1550)
+ MAC_RES(AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT),
+#elif defined(CONFIG_SOC_AU1500)
+ MAC_RES(AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT),
+#endif
+};
+
+static struct au1000_eth_platform_data au1xxx_eth0_platform_data = {
+ .phy1_search_mac0 = 1,
+};
+
+static struct platform_device au1xxx_eth0_device = {
+ .name = "au1000-eth",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(au1xxx_eth0_resources),
+ .resource = au1xxx_eth0_resources,
+ .dev.platform_data = &au1xxx_eth0_platform_data,
+};
+
+#ifndef CONFIG_SOC_AU1100
+static struct au1000_eth_platform_data au1xxx_eth1_platform_data = {
+ .phy1_search_mac0 = 1,
+};
+
+static struct platform_device au1xxx_eth1_device = {
+ .name = "au1000-eth",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(au1xxx_eth1_resources),
+ .resource = au1xxx_eth1_resources,
+ .dev.platform_data = &au1xxx_eth1_platform_data,
+};
+#endif
+
+void __init au1xxx_override_eth_cfg(unsigned int port,
+ struct au1000_eth_platform_data *eth_data)
+{
+ if (!eth_data || port > 1)
+ return;
+
+ if (port == 0)
+ memcpy(&au1xxx_eth0_platform_data, eth_data,
+ sizeof(struct au1000_eth_platform_data));
+#ifndef CONFIG_SOC_AU1100
+ else
+ memcpy(&au1xxx_eth1_platform_data, eth_data,
+ sizeof(struct au1000_eth_platform_data));
+#endif
+}
+
static struct platform_device *au1xxx_platform_devices[] __initdata = {
&au1xx0_uart_device,
&au1xxx_usb_ohci_device,
@@ -345,6 +428,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
#ifdef SMBUS_PSC_BASE
&pbdb_smbus_device,
#endif
+ &au1xxx_eth0_device,
};
static int __init au1xxx_platform_init(void)
@@ -356,6 +440,12 @@ static int __init au1xxx_platform_init(void)
for (i = 0; au1x00_uart_data[i].flags; i++)
au1x00_uart_data[i].uartclk = uartclk;
+#ifndef CONFIG_SOC_AU1100
+ /* Register second MAC if enabled in pinfunc */
+ if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2))
+ platform_device_register(&au1xxx_eth1_device);
+#endif
+
return platform_add_devices(au1xxx_platform_devices,
ARRAY_SIZE(au1xxx_platform_devices));
}
diff --git a/arch/mips/alchemy/devboards/db1x00/board_setup.c b/arch/mips/alchemy/devboards/db1x00/board_setup.c
index 7aee14d..ad26db2 100644
--- a/arch/mips/alchemy/devboards/db1x00/board_setup.c
+++ b/arch/mips/alchemy/devboards/db1x00/board_setup.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_eth.h>
#include <asm/mach-db1x00/db1x00.h>
#include <asm/mach-db1x00/bcsr.h>
@@ -43,6 +44,18 @@ char irq_tab_alchemy[][5] __initdata = {
[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD }, /* IDSEL 13 - PCI slot */
};
#endif
+
+/*
+ * Micrel/Kendin 5 port switch attached to MAC0,
+ * MAC0 is associated with PHY address 5 (== WAN port)
+ * MAC1 is not associated with any PHY, since it's connected directly
+ * to the switch.
+ * no interrupts are used
+ */
+static struct au1000_eth_platform_data eth0_pdata = {
+ .phy_static_config = 1,
+ .phy_addr = 5,
+};
#ifdef CONFIG_MIPS_BOSPORUS
char irq_tab_alchemy[][5] __initdata = {
@@ -50,6 +63,8 @@ char irq_tab_alchemy[][5] __initdata = {
[12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff }, /* IDSEL 12 - SN1741 */
[13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD }, /* IDSEL 13 - PCI slot */
};
+
+
#endif
#ifdef CONFIG_MIPS_MIRAGE
@@ -103,6 +118,8 @@ void __init board_setup(void)
printk(KERN_INFO "AMD Alchemy Au1100/Db1100 Board\n");
#endif
#ifdef CONFIG_MIPS_BOSPORUS
+ au1xxx_override_eth_cfg(0, ð0_pdata);
+
printk(KERN_INFO "AMD Alchemy Bosporus Board\n");
#endif
#ifdef CONFIG_MIPS_MIRAGE
diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h b/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h
new file mode 100644
index 0000000..f30529e
--- /dev/null
+++ b/arch/mips/include/asm/mach-au1x00/au1xxx_eth.h
@@ -0,0 +1,18 @@
+#ifndef __AU1X00_ETH_DATA_H
+#define __AU1X00_ETH_DATA_H
+
+/* Platform specific PHY configuration passed to the MAC driver */
+struct au1000_eth_platform_data {
+ int phy_static_config;
+ int phy_search_highest_addr;
+ int phy1_search_mac0;
+ int phy_addr;
+ int phy_busid;
+ int phy_irq;
+};
+
+void __init au1xxx_override_eth_cfg(unsigned port,
+ struct au1000_eth_platform_data *eth_data);
+
+#endif /* __AU1X00_ETH_DATA_H */
+
^ permalink raw reply related
* Re: [RFC,PATCH] mutex: mutex_is_owner() helper
From: Eric Dumazet @ 2009-11-09 23:21 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Ingo Molnar, Linus Torvalds, David S. Miller, Linux Netdev List,
linux kernel, Thomas Gleixner
In-Reply-To: <1257792987.4108.364.camel@laptop>
Peter Zijlstra a écrit :
> On Wed, 2009-11-04 at 18:19 +0100, Eric Dumazet wrote:
>> BTW, I was thinking of a mutex_yield() implementation, but could not
>> cook it without hard thinking, maybe you already have some nice
>> implementation ?
>
> Why? Yield sets off alarm bells, since 99.9%, and possibly more, of its
> uses are wrong.
If I remember well, I had problems doing "modprobe dummy numdummies=30000",
because it creates 30000 netdevices, and thanks to hotplug starts 30000 udev
that all wait that my modprobe is finished... Nice to see load average going
so big by the way :)
I tried following patch without success, because rtnl_unlock()/rtnl_lock()
is too fast (awaken process(es) ha(s/ve) no chance to get the lock, as we
take it immediately after releasing it)
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 37dcfdc..3de1466 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -138,8 +138,11 @@ static int __init dummy_init_module(void)
rtnl_lock();
err = __rtnl_link_register(&dummy_link_ops);
- for (i = 0; i < numdummies && !err; i++)
+ for (i = 0; i < numdummies && !err; i++) {
err = dummy_init_one();
+ rtnl_unlock();
+ rtnl_lock();
+ }
if (err < 0)
__rtnl_link_unregister(&dummy_link_ops);
rtnl_unlock();
Then I added a msleep(1) between the unlock/lock and got beter results.
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 37dcfdc..108c4fa 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -138,8 +138,12 @@ static int __init dummy_init_module(void)
rtnl_lock();
err = __rtnl_link_register(&dummy_link_ops);
- for (i = 0; i < numdummies && !err; i++)
+ for (i = 0; i < numdummies && !err; i++) {
err = dummy_init_one();
+ rtnl_unlock();
+ msleep(1);
+ rtnl_lock();
+ }
if (err < 0)
__rtnl_link_unregister(&dummy_link_ops);
rtnl_unlock();
But if hotplug is disabled, this force a useless msleep(1) * 30000 -> this is bit slow
Yes, this code is stupid, but I use it to stress network stack
with insane number of devices, to spot scalability problems.
mutex_yield() could help in this situation.
mutex is said to be FIFO, but its not exactly true : A new comer can take the mutex
even if 10000 threads are waiting on mutex...
I wont mention other problems, because mutex_{try}lock() has no timedwait variant, and
funny code doing :
if (!rtnl_trylock())
return restart_syscall();
Making 30000 processes running/fighting to get the mutex :(
^ permalink raw reply related
* Re: [PATCH] IPv6: use ipv6_addr_v4mapped()
From: Eric Dumazet @ 2009-11-09 22:59 UTC (permalink / raw)
To: Brian Haley; +Cc: David Miller, netdev@vger.kernel.org
In-Reply-To: <4AF89241.7060203@hp.com>
Brian Haley a écrit :
> Change udp6_portaddr_hash() to use ipv6_addr_v4mapped()
> inline instead of ipv6_addr_type().
>
> Signed-off-by: Brian Haley <brian.haley@hp.com>
> ---
>
> diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
> index 2915e1d..0ed1637 100644
> --- a/net/ipv6/udp.c
> +++ b/net/ipv6/udp.c
> @@ -89,7 +89,7 @@ static unsigned int udp6_portaddr_hash(struct net *net,
>
> if (ipv6_addr_any(addr6))
> hash = jhash_1word(0, mix);
> - else if (ipv6_addr_type(addr6) == IPV6_ADDR_MAPPED)
> + else if (ipv6_addr_v4mapped(addr6))
> hash = jhash_1word(addr6->s6_addr32[3], mix);
> else
> hash = jhash2(addr6->s6_addr32, 4, mix);
Indeed, its a bit faster ;)
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Thanks Brian
^ permalink raw reply
* [PATCH] IPv6: use ipv6_addr_v4mapped()
From: Brian Haley @ 2009-11-09 22:05 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org
Change udp6_portaddr_hash() to use ipv6_addr_v4mapped()
inline instead of ipv6_addr_type().
Signed-off-by: Brian Haley <brian.haley@hp.com>
---
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 2915e1d..0ed1637 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -89,7 +89,7 @@ static unsigned int udp6_portaddr_hash(struct net *net,
if (ipv6_addr_any(addr6))
hash = jhash_1word(0, mix);
- else if (ipv6_addr_type(addr6) == IPV6_ADDR_MAPPED)
+ else if (ipv6_addr_v4mapped(addr6))
hash = jhash_1word(addr6->s6_addr32[3], mix);
else
hash = jhash2(addr6->s6_addr32, 4, mix);
^ permalink raw reply related
* [PATCH net-next-2.6] ipv6: speedup inet6_dump_ifinfo()
From: Eric Dumazet @ 2009-11-09 22:11 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List
When handling large number of netdevice, inet6_dump_ifinfo()
is very slow because it has O(N^2) complexity.
Instead of scanning one single list, we can use the 256 sub lists
of the dev_index hash table, and RCU lookups.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/ipv6/addrconf.c | 45 ++++++++++++++++++++++++++----------------
1 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 024bba3..f9f7fd6 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3823,28 +3823,39 @@ nla_put_failure:
static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
- int idx, err;
- int s_idx = cb->args[0];
+ int h, s_h;
+ int idx = 0, err, s_idx;
struct net_device *dev;
struct inet6_dev *idev;
+ struct hlist_head *head;
+ struct hlist_node *node;
- read_lock(&dev_base_lock);
- idx = 0;
- for_each_netdev(net, dev) {
- if (idx < s_idx)
- goto cont;
- if ((idev = in6_dev_get(dev)) == NULL)
- goto cont;
- err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
- in6_dev_put(idev);
- if (err <= 0)
- break;
+ s_h = cb->args[0];
+ s_idx = cb->args[1];
+
+ rcu_read_lock();
+ for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+ idx = 0;
+ head = &net->dev_index_head[h];
+ hlist_for_each_entry_rcu(dev, node, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+ idev = __in6_dev_get(dev);
+ if (!idev)
+ goto cont;
+ if (inet6_fill_ifinfo(skb, idev,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWLINK, NLM_F_MULTI) <= 0)
+ goto out;
cont:
- idx++;
+ idx++;
+ }
}
- read_unlock(&dev_base_lock);
- cb->args[0] = idx;
+out:
+ rcu_read_unlock();
+ cb->args[1] = idx;
+ cb->args[0] = h;
return skb->len;
}
^ permalink raw reply related
* [PATCH] e1000e: Fix usage under kexec
From: Sven Anders @ 2009-11-09 20:25 UTC (permalink / raw)
To: netdev
[-- Attachment #1.1: Type: text/plain, Size: 1516 bytes --]
Hello!
We're experiencing the following problem:
We start a minimal linux system, prepare the system and start the
final system via kexec.
On two different systems (one with a 82573 and one with a 82574),
the driver cannot initialize the network hardware, because the PHY
is not recognized.
We get the following error:
e1000e: probe of 0000:02:00.0 failed with error -2
We cannot unload the driver of the first kernel, because it's
compiled in statically.
It's caused by the PHY, because it's already initialized by the
first driver and therefore does not respond correctly. The driver
assumes the PHY to be in 'reset' state, which is done by the BIOS.
We fixed it by adding a
+ /* Reset PHY before initializing it. Allows re-init after kexec. */
+ if (!e1000_check_reset_block(hw))
+ e1000_phy_hw_reset(hw);
to the initialization routine. I'm not sure, if we need the additional
"block" check.
A patch is attached.
Please send a note, if the patch is correct or wrong...
Regards
Sven Anders
--
Sven Anders <anders@anduras.de> () Ascii Ribbon Campaign
/\ Support plain text e-mail
ANDURAS service solutions AG
Innstrasse 71 - 94036 Passau - Germany
Web: www.anduras.de - Tel: +49 (0)851-4 90 50-0 - Fax: +49 (0)851-4 90 50-55
Those who would give up essential Liberty, to purchase a little
temporary Safety, deserve neither Liberty nor Safety.
- Benjamin Franklin
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: e1000e-kexec.patch --]
[-- Type: text/x-patch; name="e1000e-kexec.patch", Size: 507 bytes --]
--- linux-2.6.29.6/drivers/net/e1000e/82571.c.orig 2009-11-04 00:44:27.000000000 +0100
+++ linux-2.6.29.6/drivers/net/e1000e/82571.c 2009-11-04 00:44:19.000000000 +0100
@@ -107,6 +107,10 @@ static s32 e1000_init_phy_params_82571(s
break;
}
+ /* Reset PHY before initializing it. Allows re-init after kexec. */
+ if (!e1000_check_reset_block(hw))
+ e1000_phy_hw_reset(hw);
+
/* This can only be done after all function pointers are setup. */
ret_val = e1000_get_phy_id_82571(hw);
[-- Attachment #1.3: sven.vcf --]
[-- Type: text/x-vcard, Size: 307 bytes --]
begin:vcard
fn:Sven Anders
n:Anders;Sven
adr;quoted-printable:;;Weidestra=C3=9Fe 19;Hannover;Niedersachsen;30453;Deutschland
email;internet:sven@anduras.de
tel;home:+49 (0)511 / 2123090
tel;cell:+49 (0)170 / 8091180
x-mozilla-html:FALSE
url:http://staff.anduras.de/anders
version:2.1
end:vcard
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]
^ permalink raw reply
* [PATCH] e1000e: Add new ID
From: Sven Anders @ 2009-11-09 20:25 UTC (permalink / raw)
To: netdev
[-- Attachment #1.1: Type: text/plain, Size: 652 bytes --]
Hello!
We use the the 82571EB (QUAD COPPER BP) with the e1000e driver.
We haven't experienced any problems yet.
The patch is trivial, just adding a new PCI ID...
Regards
Sven Anders
--
Sven Anders <anders@anduras.de> () Ascii Ribbon Campaign
/\ Support plain text e-mail
ANDURAS service solutions AG
Innstrasse 71 - 94036 Passau - Germany
Web: www.anduras.de - Tel: +49 (0)851-4 90 50-0 - Fax: +49 (0)851-4 90 50-55
Those who would give up essential Liberty, to purchase a little
temporary Safety, deserve neither Liberty nor Safety.
- Benjamin Franklin
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: e1000e-Add_ID_01A0.patch --]
[-- Type: text/x-patch; name="e1000e-Add_ID_01A0.patch", Size: 1724 bytes --]
--- linux-2.6.26.2/drivers/net/e1000e/hw.h.orig 2008-09-29 14:20:55.000000000 +0200
+++ linux-2.6.26.2/drivers/net/e1000e/hw.h 2008-09-29 14:26:38.000000000 +0200
@@ -323,6 +323,7 @@
#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5
#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC
+#define E1000_DEV_ID_82571EB_QUAD_COPPER_BP 0x10A0
#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA
#define E1000_DEV_ID_82572EI_COPPER 0x107D
--- linux-2.6.26.2/drivers/net/e1000e/netdev.c.orig 2008-09-29 14:27:01.000000000 +0200
+++ linux-2.6.26.2/drivers/net/e1000e/netdev.c 2008-09-29 14:27:29.000000000 +0200
@@ -4560,6 +4560,7 @@
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), board_82571 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_BP), board_82571 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 },
--- linux-2.6.26.2/drivers/net/e1000e/82571.c.orig 2008-09-29 14:27:42.000000000 +0200
+++ linux-2.6.26.2/drivers/net/e1000e/82571.c 2008-09-29 14:28:04.000000000 +0200
@@ -274,6 +274,7 @@
case E1000_DEV_ID_82571EB_QUAD_COPPER:
case E1000_DEV_ID_82571EB_QUAD_FIBER:
case E1000_DEV_ID_82571EB_QUAD_COPPER_LP:
+ case E1000_DEV_ID_82571EB_QUAD_COPPER_BP:
case E1000_DEV_ID_82571PT_QUAD_COPPER:
adapter->flags |= FLAG_IS_QUAD_PORT;
/* mark the first port */
[-- Attachment #1.3: sven.vcf --]
[-- Type: text/x-vcard, Size: 307 bytes --]
begin:vcard
fn:Sven Anders
n:Anders;Sven
adr;quoted-printable:;;Weidestra=C3=9Fe 19;Hannover;Niedersachsen;30453;Deutschland
email;internet:sven@anduras.de
tel;home:+49 (0)511 / 2123090
tel;cell:+49 (0)170 / 8091180
x-mozilla-html:FALSE
url:http://staff.anduras.de/anders
version:2.1
end:vcard
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]
^ 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