* Re: 2.6.23-rc2-mm2
From: Dave Young @ 2007-08-10 9:52 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, netdev
In-Reply-To: <a8e1da0708100137t48c5c673vf0c98fb5f0cd058b@mail.gmail.com>
>On 8/10/07, Dave Young <hidave.darkstar@gmail.com> wrote:
> >On 8/10/07, Andrew Morton <akpm@linux-foundation.org> wrote:
> > On Fri, 10 Aug 2007 16:18:38 +0800 "Dave Young" <hidave.darkstar@gmail.com> wrote:
> >
> > > Hi,
> > > 2.6.23-rc2-mm2:
> > > config with CONFIG_NF_CONNTRACK_AMANDA=y
> > > boot oops:
> > >
> > > hand copyed :
> > > the EIP: helper_hash
> > >
> > > backtrace:
> > > do_basic_setup
> > > ...
> > > nf_conntrack_amanda_init
> > > error_code
> > > do_vivide_error
> > > ...
> > >
> >
> > cc netdev
> >
> > please send config
> >
> > presumably nf_ct_helper_hsize is zero
> >
> > I'd have thought that the same bug would be present in mainline - there's
> > nothing in git-net.patch.
> >
> > (hunts around, discovers that there's a net-2.6.24 tree now. Bah)
> >
> MY config file for test:
>-----cut---
Hi,
config the CONFIG_NF_CONNTRACK_AMANDA=m, reboot , still oops, but this
time the point is nf_conntrack_ftp_init, (I doubt the
nf_conntrack_core is not initialized.)
boot with vga_ask and select 80x60, copyed more infomations:
---------pre oops:-----------
sysctl table check failed: /net/netfilter/nf_conntrack_generic_timeout
.3.19.13 Missing strategy
...
nf_conntrack_14_proto_sctp4 protocol register failed
...
---------oops:----------------
divide error: 0000 [#1] SMP
EIP: 0060: [<c088477b>] EFLAGS 00010246
Process swapper
...
nf_conntrack_ftp_init
...
Code: <...>
EIP <...> helper_hash +0x1b/0x24
Regards
dave
^ permalink raw reply
* Re: 2.6.23-rc2: WARNING: at kernel/irq/resend.c:70 check_irq_resend()
From: Jarek Poplawski @ 2007-08-10 10:05 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, John Stoffel, linux-kernel, shemminger, vignaud,
marcin.slusarz, torvalds, akpm, alan, linux-net, netdev
In-Reply-To: <20070810093353.GA19777@elte.hu>
On Fri, Aug 10, 2007 at 11:33:53AM +0200, Ingo Molnar wrote:
>
> * Jarek Poplawski <jarkao2@o2.pl> wrote:
>
> > > > > + }
> > > > > #ifdef CONFIG_HARDIRQS_SW_RESEND
> > >
> > > we used the hw-resend method unconditionally, right?
> >
> > Right: unconditionally on a condition they are not edges...
> >
> > But, since not resending at all seems to work so good in testing, I
> > thought, _SW_RESEND could be considered as an unnecessarily
> > complicated alternative.
> >
> > Now, I'm a bit confused...
>
> the idea is multi-pronged:
>
> - Primarily, we want to fix the regression. 2.6.20 worked, 2.6.21
> didnt, that has to be fixed, no matter what - end of story. But we've
> got a wide selection of patches for that purpose now, so what matters
> at this point is the secondary question:
>
> - we want to know _why exactly_ the hang happens. We now have a pretty
> good theory: hw-resend hangs the IO-APIC. (there is a delicate dance
> between local APICs and IO-APICs for level-triggered irqs, and if we
> interject via hw-resending via the local APIC, existing races, hw
> bugs or weaknesses in our hw-resend implementation might be exposed)
>
> and even though we now have a wide selection of patches we really want
> to get to the bottom of the problem so that we can fix the bug that got
> exposed: apparently hw resend doesnt always work with level-triggered
> irqs.
>
> Note that the hw-resend sequence can trigger _even without our original
> patch that triggered the regression_, it's just much less likely to
> happen, so this is a pre-existing IO-APIC/APIC code bug that could
> trigger anytime, and which we want to see fixed.
>
> To confirm this theory - does the debug-patch below fix the hang? If it
> fixes the hang then the theory is confirmed and then the right solution
> is to retrigger an IRQ for level-triggered irqs with the proper
> trigger-type set.
>
> Ingo
Ingo: I think, you have to do this in x86_64, and there is probably
send_IPI_mask used for this (but I can miss something...).
I think, Marcin will not be able to do this and report before monday,
but,
Jean-Baptiste: of course current Ingo's or Thomas' patches are
more urgent, so if you could break the current test and try this
(maybe after Ingo acks this yet?) with eg. clean 2.6.23-rc1 or 2.6.22?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jarek P.
>
> ------------------>
> Not-Signed-off-by: Ingo Molnar <mingo@elte.hu>
>
> Index: linux/arch/i386/kernel/io_apic.c
> ===================================================================
> --- linux.orig/arch/i386/kernel/io_apic.c
> +++ linux/arch/i386/kernel/io_apic.c
> @@ -735,7 +735,8 @@ void fastcall send_IPI_self(int vector)
> * Wait for idle.
> */
> apic_wait_icr_idle();
> - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
> + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL |
> + APIC_INT_LEVELTRIG;
> /*
> * Send the IPI. The write to APIC_ICR fires this off.
> */
>
^ permalink raw reply
* Re: 2.6.23-rc2: WARNING: at kernel/irq/resend.c:70 check_irq_resend()
From: Stephen Hemminger @ 2007-08-10 10:13 UTC (permalink / raw)
To: Ingo Molnar
Cc: Jarek Poplawski, Thomas Gleixner, John Stoffel, linux-kernel,
vignaud, marcin.slusarz, torvalds, akpm, alan, linux-net, netdev
In-Reply-To: <20070810093353.GA19777@elte.hu>
On Fri, 10 Aug 2007 11:33:53 +0200
Ingo Molnar <mingo@elte.hu> wrote:
>
> * Jarek Poplawski <jarkao2@o2.pl> wrote:
>
> > > > > + }
> > > > > #ifdef CONFIG_HARDIRQS_SW_RESEND
> > >
> > > we used the hw-resend method unconditionally, right?
> >
> > Right: unconditionally on a condition they are not edges...
> >
> > But, since not resending at all seems to work so good in testing, I
> > thought, _SW_RESEND could be considered as an unnecessarily
> > complicated alternative.
> >
> > Now, I'm a bit confused...
>
> the idea is multi-pronged:
>
> - Primarily, we want to fix the regression. 2.6.20 worked, 2.6.21
> didnt, that has to be fixed, no matter what - end of story. But we've
> got a wide selection of patches for that purpose now, so what matters
> at this point is the secondary question:
>
> - we want to know _why exactly_ the hang happens. We now have a pretty
> good theory: hw-resend hangs the IO-APIC. (there is a delicate dance
> between local APICs and IO-APICs for level-triggered irqs, and if we
> interject via hw-resending via the local APIC, existing races, hw
> bugs or weaknesses in our hw-resend implementation might be exposed)
>
> and even though we now have a wide selection of patches we really want
> to get to the bottom of the problem so that we can fix the bug that got
> exposed: apparently hw resend doesnt always work with level-triggered
> irqs.
>
> Note that the hw-resend sequence can trigger _even without our original
> patch that triggered the regression_, it's just much less likely to
> happen, so this is a pre-existing IO-APIC/APIC code bug that could
> trigger anytime, and which we want to see fixed.
>
> To confirm this theory - does the debug-patch below fix the hang? If it
> fixes the hang then the theory is confirmed and then the right solution
> is to retrigger an IRQ for level-triggered irqs with the proper
> trigger-type set.
>
All this might explain some of the IRQ loss, I saw with sky2 on mac mini.
Basically, the device would act like it missed an IRQ. The chip and PCI registers
all said "device has asserted IRQ" but the IRQ handler never got called.
Then again, the problem might be completely different since this was with
PCI-E with either MSI or INTA mode.
The workaround was to perodically call the soft IRQ handler and that would
clear the IRQ, but it's not something I want to keep.
^ permalink raw reply
* Re: 2.6.23-rc2: WARNING: at kernel/irq/resend.c:70 check_irq_resend()
From: Ingo Molnar @ 2007-08-10 10:16 UTC (permalink / raw)
To: Jarek Poplawski
Cc: Thomas Gleixner, John Stoffel, linux-kernel, shemminger, vignaud,
marcin.slusarz, torvalds, akpm, alan, linux-net, netdev
In-Reply-To: <20070810100513.GA3279@ff.dom.local>
* Jarek Poplawski <jarkao2@o2.pl> wrote:
> Ingo: I think, you have to do this in x86_64, and there is probably
> send_IPI_mask used for this (but I can miss something...).
indeed - full patch below.
Ingo
---
arch/i386/kernel/io_apic.c | 3 ++-
arch/x86_64/kernel/genapic.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
Index: linux/arch/i386/kernel/io_apic.c
===================================================================
--- linux.orig/arch/i386/kernel/io_apic.c
+++ linux/arch/i386/kernel/io_apic.c
@@ -735,7 +735,8 @@ void fastcall send_IPI_self(int vector)
* Wait for idle.
*/
apic_wait_icr_idle();
- cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+ cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL |
+ APIC_INT_LEVELTRIG;
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
Index: linux/arch/x86_64/kernel/genapic.c
===================================================================
--- linux.orig/arch/x86_64/kernel/genapic.c
+++ linux/arch/x86_64/kernel/genapic.c
@@ -62,5 +62,6 @@ void __init setup_apic_routing(void)
void send_IPI_self(int vector)
{
- __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+ __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL |
+ APIC_INT_LEVELTRIG);
}
^ permalink raw reply
* Re: [patch (testing)] Re: 2.6.20->2.6.21 - networking dies after random time
From: Marcin Ślusarz @ 2007-08-10 10:43 UTC (permalink / raw)
To: Jarek Poplawski
Cc: Ingo Molnar, Thomas Gleixner, Linus Torvalds,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Alan Cox
In-Reply-To: <20070810071038.GA1764@ff.dom.local>
2007/8/10, Jarek Poplawski <jarkao2@o2.pl>:
> (..)
> I think, there is this one possible for your testing yet?:
> Subject: [patch] genirq: temporary fix for level-triggered IRQ resend
> Date: Wed, 8 Aug 2007 13:00:37 +0200
I think I already tested this patch, but this thread is sooo big and I
can't find my response...
> If it's not a great problem it would be interesting to try this with
> different CONFIG_HZ too e.g. you could start with 100 (I guess, you
> tested very similar thing in 2.6.23-rc2 with 1000(?) already).
My all tests were done on 2.6.22.1
Marcin
^ permalink raw reply
* Re: [PATCH 13/24] make atomic_read() behave consistently on mips
From: Ralf Baechle @ 2007-08-09 20:09 UTC (permalink / raw)
To: Chris Snook
Cc: linux-kernel, linux-arch, torvalds, netdev, akpm, ak,
heiko.carstens, davem, schwidefsky, wensong, horms, wjiang,
cfriesen, zlynx, rpjday, jesper.juhl
In-Reply-To: <20070809140004.GA17112@shell.boston.redhat.com>
On Thu, Aug 09, 2007 at 10:00:04AM -0400, Chris Snook wrote:
> Purify volatile use for atomic[64]_t on mips.
>
> Signed-off-by: Chris Snook <csnook@redhat.com>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
^ permalink raw reply
* Re: 2.6.23-rc2-mm2
From: Gabriel C @ 2007-08-10 11:19 UTC (permalink / raw)
To: Dave Young; +Cc: Andrew Morton, linux-kernel, netdev
In-Reply-To: <a8e1da0708100252g5597da63j9cb665ade26f7654@mail.gmail.com>
Dave Young wrote:
>> On 8/10/07, Dave Young <hidave.darkstar@gmail.com> wrote:
>>> On 8/10/07, Andrew Morton <akpm@linux-foundation.org> wrote:
>>> On Fri, 10 Aug 2007 16:18:38 +0800 "Dave Young" <hidave.darkstar@gmail.com> wrote:
>>>
>>>> Hi,
>>>> 2.6.23-rc2-mm2:
>>>> config with CONFIG_NF_CONNTRACK_AMANDA=y
>>>> boot oops:
>>>>
>>>> hand copyed :
>>>> the EIP: helper_hash
>>>>
>>>> backtrace:
>>>> do_basic_setup
>>>> ...
>>>> nf_conntrack_amanda_init
>>>> error_code
>>>> do_vivide_error
>>>> ...
>>>>
>>> cc netdev
>>>
>>> please send config
>>>
>>> presumably nf_ct_helper_hsize is zero
>>>
>>> I'd have thought that the same bug would be present in mainline - there's
>>> nothing in git-net.patch.
>>>
>>> (hunts around, discovers that there's a net-2.6.24 tree now. Bah)
>>>
>> MY config file for test:
>> -----cut---
> Hi,
> config the CONFIG_NF_CONNTRACK_AMANDA=m, reboot , still oops, but this
> time the point is nf_conntrack_ftp_init, (I doubt the
> nf_conntrack_core is not initialized.)
>
> boot with vga_ask and select 80x60, copyed more infomations:
> ---------pre oops:-----------
> sysctl table check failed: /net/netfilter/nf_conntrack_generic_timeout
> .3.19.13 Missing strategy
> ...
> nf_conntrack_14_proto_sctp4 protocol register failed
> ...
> ---------oops:----------------
> divide error: 0000 [#1] SMP
> EIP: 0060: [<c088477b>] EFLAGS 00010246
> Process swapper
> ...
> nf_conntrack_ftp_init
> ...
>
> Code: <...>
> EIP <...> helper_hash +0x1b/0x24
Does not Oops here but is broken.
Here is what I get :
modprobe nf_conntrack_amanda
WARNING: Error inserting nf_conntrack (/lib/modules/2.6.23-rc2-mm2/kernel/net/netfilter/nf_conntrack.ko): Cannot allocate memory
FATAL: Error inserting nf_conntrack_amanda (/lib/modules/2.6.23-rc2-mm2/kernel/net/netfilter/nf_conntrack_amanda.ko): Unknown symbol in module, or unknown parameter (see dmesg)
( from dmesg )
...
[ 1094.768867] nf_conntrack version 0.5.0 (10240 buckets, 40960 max)
[ 1094.769078] sysctl table check failed: /net/netfilter/nf_conntrack_generic_timeout .3.19.13 Missing strategy
[ 1094.780956] nf_conntrack_amanda: Unknown symbol nf_ct_expect_alloc
[ 1094.781055] nf_conntrack_amanda: Unknown symbol nf_ct_expect_put
[ 1094.781242] nf_conntrack_amanda: Unknown symbol nf_ct_expect_init
[ 1094.781371] nf_conntrack_amanda: Unknown symbol nf_conntrack_helper_unregister
[ 1094.781468] nf_conntrack_amanda: Unknown symbol __nf_ct_refresh_acct
[ 1094.781580] nf_conntrack_amanda: Unknown symbol nf_ct_expect_related
[ 1094.781673] nf_conntrack_amanda: Unknown symbol nf_conntrack_helper_register
...
>
> Regards
> dave
> -
Gabriel
^ permalink raw reply
* [PATCH net-2.6.24] [TCP]: Update comment about highest_sack validity
From: Ilpo Järvinen @ 2007-08-10 11:30 UTC (permalink / raw)
To: David Miller; +Cc: Netdev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 937 bytes --]
This stale info came from the original idea, which proved to be
unnecessarily complex, sacked_out > 0 is easy to do and that when
it's going to be needed anyway (it _can_ be valid also when
sacked_out == 0 but there's not going to be a guarantee about it
for now).
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
---
include/linux/tcp.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 1f12fa0..f8cf090 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -332,7 +332,8 @@ struct tcp_sock {
struct tcp_sack_block_wire recv_sack_cache[4];
- u32 highest_sack; /* Start seq of globally highest revd SACK (valid only in slowpath) */
+ u32 highest_sack; /* Start seq of globally highest revd SACK
+ * (validity guaranteed only if sacked_out > 0) */
/* from STCP, retrans queue hinting */
struct sk_buff* lost_skb_hint;
--
1.5.0.6
^ permalink raw reply related
* Re: 2.6.23-rc2: WARNING: at kernel/irq/resend.c:70 check_irq_resend()
From: Jean-Baptiste Vignaud @ 2007-08-10 11:35 UTC (permalink / raw)
To: jarkao2
Cc: mingo, tglx, john, linux-kernel, shemminger, marcin.slusarz,
torvalds, akpm, alan, linux-net, netdev
> Ingo: I think, you have to do this in x86_64, and there is probably
> send_IPI_mask used for this (but I can miss something...).
>
> I think, Marcin will not be able to do this and report before monday,
> but,
> Jean-Baptiste: of course current Ingo's or Thomas' patches are
> more urgent, so if you could break the current test and try this
> (maybe after Ingo acks this yet?) with eg. clean 2.6.23-rc1 or 2.6.22?
>
i'm compiling 2.6.23-rc1 with http://lkml.org/lkml/diff/2007/8/10/101/1
when finished, i'll stop current test (atm : about 100Go of network traffic and still ok) to try it.
Jb
^ permalink raw reply
* Re: [patch (testing)] Re: 2.6.20->2.6.21 - networking dies after random time
From: Jarek Poplawski @ 2007-08-10 11:37 UTC (permalink / raw)
To: Marcin Ślusarz
Cc: Ingo Molnar, Thomas Gleixner, Linus Torvalds,
Jean-Baptiste Vignaud, linux-kernel, shemminger, linux-net,
netdev, Andrew Morton, Alan Cox
In-Reply-To: <4bacf17f0708100343r950cf90kbf826e2afc826df5@mail.gmail.com>
On Fri, Aug 10, 2007 at 12:43:43PM +0200, Marcin Ślusarz wrote:
> 2007/8/10, Jarek Poplawski <jarkao2@o2.pl>:
> > (..)
> > I think, there is this one possible for your testing yet?:
> > Subject: [patch] genirq: temporary fix for level-triggered IRQ resend
> > Date: Wed, 8 Aug 2007 13:00:37 +0200
> I think I already tested this patch, but this thread is sooo big and I
> can't find my response...
I think it was very similar Ingo's patch, which after your testing
is in 2.6.23-rc2 now. I've moved return for level type irqs a little
later, and it works a new way only for "x86_64".
But, I think, now this patch is less important: if you find some time,
try mostly new Ingo's or Thomas' patches (latest possible versions).
>
> > If it's not a great problem it would be interesting to try this with
> > different CONFIG_HZ too e.g. you could start with 100 (I guess, you
> > tested very similar thing in 2.6.23-rc2 with 1000(?) already).
> My all tests were done on 2.6.22.1
Fine! If it's not said otherwise this version should be appropriate for
most of these patches. But, please, send your current configs on next
posibility (dmesg, /proc/interrupts and .config).
Bye (till monday),
Jarek P.
^ permalink raw reply
* Re: [PATCH 1/1] af_packet: don't enable timestamps in mmap'ed sockets
From: Unai Uribarri @ 2007-08-10 11:55 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: netdev, linux-kernel
In-Reply-To: <20070810083418.GA25479@2ka.mipt.ru>
On vie, 2007-08-10 at 12:34 +0400, Evgeniy Polyakov wrote:
> Hi Unai.
>
> On Thu, Aug 09, 2007 at 08:44:21PM +0200, Unai Uribarri (unai.uribarri@optenet.com) wrote:
> > There is another option:
> >
> > 1. Move timestampt activation to packet_set_ring(), so it's activated
> > only once at setup instead of every time a packet arrives.
>
> Does this break existing systems which expects timestamp be turned on
> always if there are packet sockets.
>
Well, current behaviour is that all packets get always timestamped if
the socket has a reception ring. We are just activating it a bit sooner
at the setsockopt(SOL_PACKET, PACKET_RX_RING) call instead of waiting
until the reception of the first packet. And current applications can't
disable it if we use a new socket option. So I can see how an
application can break.
> > 2. Fix sock_setsockopt() so setting SO_TIMESTAMP to 0 effectively
> > disables timestamp.
>
> This breaks compatibility. Add new socket option, which will really
> disable it and do all your logic, but not breaking existing
> applications.
>
Is SO_TIMESTAMP2 a valid name? I can't imagine how to call it.
^ permalink raw reply
* Re: [PATCH 1/1] af_packet: don't enable timestamps in mmap'ed sockets
From: Evgeniy Polyakov @ 2007-08-10 12:14 UTC (permalink / raw)
To: Unai Uribarri; +Cc: netdev, linux-kernel
In-Reply-To: <1186746907.24669.107.camel@localhost.localdomain>
On Fri, Aug 10, 2007 at 01:55:07PM +0200, Unai Uribarri (unai.uribarri@optenet.com) wrote:
> > This breaks compatibility. Add new socket option, which will really
> > disable it and do all your logic, but not breaking existing
> > applications.
> >
>
> Is SO_TIMESTAMP2 a valid name? I can't imagine how to call it.
:) what about name, which really shows what option does?
--
Evgeniy Polyakov
^ permalink raw reply
* Re: 2.6.23-rc2: WARNING: at kernel/irq/resend.c:70 check_irq_resend()
From: Jean-Baptiste Vignaud @ 2007-08-10 12:27 UTC (permalink / raw)
To: mingo
Cc: jarkao2, tglx, john, linux-kernel, shemminger, marcin.slusarz,
torvalds, akpm, alan, linux-net, netdev
see below
> arch/i386/kernel/io_apic.c | 3 ++-
> arch/x86_64/kernel/genapic.c | 3 ++-
> 2 files changed, 4 insertions(+), 2 deletions(-)
>
> Index: linux/arch/i386/kernel/io_apic.c
> ===================================================================
> --- linux.orig/arch/i386/kernel/io_apic.c
> +++ linux/arch/i386/kernel/io_apic.c
> @@ -735,7 +735,8 @@ void fastcall send_IPI_self(int vector)
> * Wait for idle.
> */
> apic_wait_icr_idle();
> - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
> + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL |
> + APIC_INT_LEVELTRIG;
> /*
> * Send the IPI. The write to APIC_ICR fires this off.
> */
> Index: linux/arch/x86_64/kernel/genapic.c
> ===================================================================
> --- linux.orig/arch/x86_64/kernel/genapic.c
> +++ linux/arch/x86_64/kernel/genapic.c
> @@ -62,5 +62,6 @@ void __init setup_apic_routing(void)
>
> void send_IPI_self(int vector)
> {
> - __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
> + __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL |
> + APIC_INT_LEVELTRIG);
> }
>
clean 2.6.23-rc1 with this patch :
Aug 10 14:12:09 loki kernel: NETDEV WATCHDOG: eth2: transmit timed out
Aug 10 14:12:09 loki kernel: eth2: transmit timed out, tx_status 00 status e601.
Aug 10 14:12:09 loki kernel: diagnostics: net 0ccc media 8880 dma 0000003a fifo 8000
Aug 10 14:12:09 loki kernel: eth2: Interrupt posted but not delivered -- IRQ blocked by another device?
Aug 10 14:12:09 loki kernel: Flags; bus-master 1, dirty 231829(5) current 231829(5)
Aug 10 14:12:09 loki kernel: Transmit list 00000000 vs. ffff81007eaad520.
Aug 10 14:12:09 loki kernel: 0: @ffff81007eaad200 length 80000115 status 0c010115
Aug 10 14:12:09 loki kernel: 1: @ffff81007eaad2a0 length 8000005c status 0c01005c
Aug 10 14:12:09 loki kernel: 2: @ffff81007eaad340 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 3: @ffff81007eaad3e0 length 8000002a status 8001002a
Aug 10 14:12:09 loki kernel: 4: @ffff81007eaad480 length 8000005c status 8c01005c
Aug 10 14:12:09 loki kernel: 5: @ffff81007eaad520 length 80000042 status 00010042
Aug 10 14:12:09 loki kernel: 6: @ffff81007eaad5c0 length 8000007b status 0001007b
Aug 10 14:12:09 loki kernel: 7: @ffff81007eaad660 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 8: @ffff81007eaad700 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 9: @ffff81007eaad7a0 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 10: @ffff81007eaad840 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 11: @ffff81007eaad8e0 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 12: @ffff81007eaad980 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 13: @ffff81007eaada20 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 14: @ffff81007eaadac0 length 8000002a status 0001002a
Aug 10 14:12:09 loki kernel: 15: @ffff81007eaadb60 length 8000002a status 0001002a
I did not had to wait too long for this to occurs (1-2 minutes).
Jb
^ permalink raw reply
* Re: [RFC PATCH v0.1] net driver: mpc52xx fec
From: Arnaldo Carvalho de Melo @ 2007-08-10 13:02 UTC (permalink / raw)
To: Domen Puncer; +Cc: linuxppc-embedded, netdev
In-Reply-To: <20070810095153.GC13994@moe.telargo.com>
Em Fri, Aug 10, 2007 at 11:51:53AM +0200, Domen Puncer escreveu:
> Hi!
>
> Not for merge (yet)! But please do review.
>
> fec_mpc52xx driver (not in-tree, but floating around) isn't in very
> good shape, so I tried to change that.
> Diff against original is quite big (fec_phy.c is completely rewritten)
> and confuzing, so I'm including whole drivers/net/fec_mpc52xx/ .
>
> I still have 'make CONFIG_FEC_MPC52xx_MDIO=n compile and work' on my
> TODO, maybe even ethtool support.
>
>
> Domen
>
>
> arch/powerpc/boot/dts/lite5200b.dts | 18
> arch/powerpc/sysdev/bestcomm/fec.h | 14
> drivers/net/fec_mpc52xx/Kconfig | 24
> drivers/net/fec_mpc52xx/Makefile | 7
> drivers/net/fec_mpc52xx/fec.c | 1002 ++++++++++++++++++++++++++++++++++++
> drivers/net/fec_mpc52xx/fec.h | 299 ++++++++++
> drivers/net/fec_mpc52xx/fec_phy.c | 229 ++++++++
> drivers/net/fec_mpc52xx/fec_phy.h | 49 +
> 8 files changed, 1641 insertions(+), 1 deletion(-)
>
> diff -pruN dummy/fec.c ./drivers/net/fec_mpc52xx/fec.c
> --- dummy/fec.c 1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec.c 2007-08-10 10:59:00.000000000 +0200
> @@ -0,0 +1,1002 @@
> +/*
> + * drivers/net/fec_mpc52xx/fec.c
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + *
> + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> and
> + * now maintained by Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
> + * Copyrigth (C) 2003-2004 MontaVista, Software, Inc.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + *
> + */
> +
> +#include <linux/module.h>
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/crc32.h>
> +#include <linux/hardirq.h>
> +
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/ethtool.h>
> +#include <linux/skbuff.h>
> +
> +#include <asm/of_device.h>
> +#include <asm/of_platform.h>
> +#include <asm/io.h>
> +#include <asm/delay.h>
> +#include <asm/mpc52xx.h>
> +
> +#include <sysdev/bestcomm/bestcomm.h>
> +#include <sysdev/bestcomm/fec.h>
> +
> +#include "fec_phy.h"
> +#include "fec.h"
> +
> +#define DRIVER_NAME "mpc52xx-fec"
> +
> +static irqreturn_t fec_interrupt(int, void *);
> +static irqreturn_t fec_rx_interrupt(int, void *);
> +static irqreturn_t fec_tx_interrupt(int, void *);
> +static struct net_device_stats *fec_get_stats(struct net_device *);
> +static void fec_set_multicast_list(struct net_device *dev);
> +static void fec_hw_init(struct net_device *dev);
> +static void fec_stop(struct net_device *dev);
> +static void fec_start(struct net_device *dev);
> +
> +static u8 mpc52xx_fec_mac_addr[6];
> +static u8 null_mac[6];
const
> +
> +static void fec_tx_timeout(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> +
> + dev_warn(&dev->dev, "transmit timed out\n");
> +
> + fec_stop(dev);
> + fec_start(dev);
> +
> + priv->stats.tx_errors++;
> +
> + if (!priv->tx_full)
> + netif_wake_queue(dev);
> +}
> +
> +static void fec_set_paddr(struct net_device *dev, u8 *mac)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> + out_be32(&fec->paddr1, *(u32*)(&mac[0]));
> + out_be32(&fec->paddr2, (*(u16*)(&mac[4]) << 16) | FEC_PADDR2_TYPE);
spaces after the types on casts to pointers
> +}
> +
> +static void fec_get_paddr(struct net_device *dev, u8 *mac)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> + *(u32*)(&mac[0]) = in_be32(&fec->paddr1);
> + *(u16*)(&mac[4]) = in_be32(&fec->paddr2) >> 16;
ditto
> +}
> +
> +static int fec_set_mac_address(struct net_device *dev, void *addr)
> +{
> + struct sockaddr *sock = (struct sockaddr *)addr;
no need for a cast, addr is a void pointer
> +
> + memcpy(dev->dev_addr, sock->sa_data, dev->addr_len);
> +
> + fec_set_paddr(dev, sock->sa_data);
> + return 0;
Why always return 0? make it void
> +}
> +
> +static void fec_free_rx_buffers(struct bcom_task *s)
> +{
> + struct sk_buff *skb;
> +
> + while (!bcom_queue_empty(s)) {
> + skb = bcom_retrieve_buffer(s, NULL, NULL);
> + kfree_skb(skb);
> + }
> +}
> +
> +static int fec_alloc_rx_buffers(struct bcom_task *rxtsk)
> +{
> + while (!bcom_queue_full(rxtsk)) {
> + struct sk_buff *skb;
> + struct bcom_fec_bd *bd;
> +
> + skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
> + if (skb == 0)
Test against NULL
> + return -EAGAIN;
> +
> + /* zero out the initial receive buffers to aid debugging */
> + memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
> +
> + bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk);
> +
> + bd->status = FEC_RX_BUFFER_SIZE;
> + bd->skb_pa = virt_to_phys(skb->data);
> +
> + bcom_submit_next_buffer(rxtsk, skb);
> + }
> +
> + return 0;
> +}
> +
> +/* based on generic_adjust_link - fs_enet-main.c */
> +static void fec_adjust_link(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct phy_device *phydev = priv->phydev;
> + int new_state = 0;
> +
> + if (phydev->link != PHY_DOWN) {
> + if (phydev->duplex != priv->duplex) {
> + new_state = 1;
> + priv->duplex = phydev->duplex;
> + }
> +
> + if (phydev->speed != priv->speed) {
> + new_state = 1;
> + priv->speed = phydev->speed;
> + }
> +
> + if (priv->link == PHY_DOWN) {
> + new_state = 1;
> + priv->link = phydev->link;
> + netif_schedule(dev);
> + netif_carrier_on(dev);
> + netif_start_queue(dev);
> + }
> +
> + } else if (priv->link) {
> + new_state = 1;
> + priv->link = PHY_DOWN;
> + priv->speed = 0;
> + priv->duplex = -1;
> + netif_stop_queue(dev);
> + netif_carrier_off(dev);
> + }
> +
> + if (new_state && netif_msg_link(priv)) {
> + phy_print_status(phydev);
> + }
No need for {}, this if has only one statement
> +}
> +
> +static int fec_init_phy(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct phy_device *phydev;
> + char phy_id[BUS_ID_SIZE];
> +
> + struct device_node *dn, *phy_dn;
> + unsigned int phy_addr;
> + const phandle *ph;
> + const unsigned int *prop;
> + struct resource res;
> + int ret;
> +
> + dn = priv->ofdev->node;
> + ph = of_get_property(dn, "phy-handle", NULL);
> + if (!ph) {
> + dev_err(&dev->dev, "can't find \"phy-handle\" in device tree\n");
> + return -ENODEV;
> + }
> + phy_dn = of_find_node_by_phandle(*ph);
> +
> + prop = of_get_property(phy_dn, "reg", NULL);
> + ret = of_address_to_resource(phy_dn->parent, 0, &res);
> + if (ret) {
> + dev_err(&dev->dev, "of_address_to_resource failed\n");
> + return ret;
> + }
> +
> + phy_addr = *prop;
> + of_node_put(phy_dn);
> +
> + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, res.start, phy_addr);
> +
> + priv->link = PHY_DOWN;
> + priv->speed = 0;
> + priv->duplex = -1;
> +
> + phydev = phy_connect(dev, phy_id, &fec_adjust_link, 0, PHY_INTERFACE_MODE_MII);
> + if (IS_ERR(phydev)) {
> + printk(KERN_ERR "%s: phy_connect failed\n", dev->name);
> + return PTR_ERR(phydev);
> + }
> +
> + phydev->advertising &= ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half;
> +
> + priv->phydev = phydev;
> +
> + return 0;
> +}
> +
> +static int fec_open(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + int err = -EBUSY;
> +
> + if (request_irq(dev->irq, &fec_interrupt, IRQF_DISABLED | IRQF_SHARED,
> + DRIVER_NAME "_ctrl", dev)) {
> + dev_err(&dev->dev, "ctrl interrupt request failed\n");
> + goto out;
> + }
> + if (request_irq(priv->r_irq, &fec_rx_interrupt, IRQF_DISABLED,
> + DRIVER_NAME "_rx", dev)) {
> + dev_err(&dev->dev, "rx interrupt request failed\n");
> + goto free_ctrl_irq;
> + }
> + if (request_irq(priv->t_irq, &fec_tx_interrupt, IRQF_DISABLED,
> + DRIVER_NAME "_tx", dev)) {
> + dev_err(&dev->dev, "tx interrupt request failed\n");
> + goto free_2irqs;
> + }
> +
> + bcom_fec_rx_reset(priv->rx_dmatsk);
> + bcom_fec_tx_reset(priv->tx_dmatsk);
> +
> + err = fec_alloc_rx_buffers(priv->rx_dmatsk);
> + if (err) {
> + dev_err(&dev->dev, "fec_alloc_rx_buffers failed\n");
> + goto free_irqs;
> + }
> +
> + err = fec_init_phy(dev);
> + if (err) {
> + dev_err(&dev->dev, "fec_init_phy failed\n");
> + goto free_skbs;
> + }
> + bcom_enable(priv->rx_dmatsk);
> + bcom_enable(priv->tx_dmatsk);
> +
> + /* reset phy - this also wakes it from PDOWN */
> + phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
> + phy_start(priv->phydev);
> +
> + fec_start(dev);
> +
> + netif_start_queue(dev);
> +
> + return 0;
> +
> + free_skbs:
> + fec_free_rx_buffers(priv->rx_dmatsk);
> +
> + free_irqs:
> + free_irq(priv->t_irq, dev);
> + free_2irqs:
> + free_irq(priv->r_irq, dev);
> + free_ctrl_irq:
> + free_irq(dev->irq, dev);
> + out:
> +
> + return err;
> +}
> +
> +static int fec_close(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> +
> + netif_stop_queue(dev);
> +
> + fec_stop(dev);
> +
> + fec_free_rx_buffers(priv->rx_dmatsk);
> +
> + phy_disconnect(priv->phydev);
> +
> + free_irq(dev->irq, dev);
> + free_irq(priv->r_irq, dev);
> + free_irq(priv->t_irq, dev);
> +
> + /* power down phy */
> + phy_stop(priv->phydev);
> + phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN);
> +
> + return 0;
> +}
> +
> +/* This will only be invoked if your driver is _not_ in XOFF state.
> + * What this means is that you need not check it, and that this
> + * invariant will hold if you make sure that the netif_*_queue()
> + * calls are done at the proper times.
> + */
> +static int fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct bcom_fec_bd *bd;
> +
> + if (bcom_queue_full(priv->tx_dmatsk)) {
> + if (net_ratelimit())
> + dev_err(&dev->dev, "transmit queue overrun\n");
> + return 1;
> + }
> +
> + spin_lock_irq(&priv->lock);
> + dev->trans_start = jiffies;
> +
> + bd = (struct bcom_fec_bd *)
> + bcom_prepare_next_buffer(priv->tx_dmatsk);
> +
> + bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_INT;
> + bd->skb_pa = virt_to_phys(skb->data);
> +
> + bcom_submit_next_buffer(priv->tx_dmatsk, skb);
> +
> + if (bcom_queue_full(priv->tx_dmatsk)) {
> + priv->tx_full = 1;
> + netif_stop_queue(dev);
> + }
> +
> + spin_unlock_irq(&priv->lock);
> +
> + return 0;
> +}
> +
> +/* This handles BestComm transmit task interrupts
> + */
> +static irqreturn_t fec_tx_interrupt(int irq, void *dev_id)
> +{
> + struct net_device *dev = dev_id;
> + struct fec_priv *priv = netdev_priv(dev);
> +
> + spin_lock(&priv->lock);
> +
> + while (bcom_buffer_done(priv->tx_dmatsk)) {
> + struct sk_buff *skb;
> + skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, NULL);
> +
> + priv->tx_full = 0;
> + dev_kfree_skb_irq(skb);
> + }
> +
> + if (netif_queue_stopped(dev) && !priv->tx_full)
> + netif_wake_queue(dev);
> +
> + spin_unlock(&priv->lock);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t fec_rx_interrupt(int irq, void *dev_id)
> +{
> + struct net_device *dev = dev_id;
> + struct fec_priv *priv = netdev_priv(dev);
> +
> + while (bcom_buffer_done(priv->rx_dmatsk)) {
> + struct sk_buff *skb;
> + struct sk_buff *rskb;
> + struct bcom_fec_bd *bd;
> + u32 status;
> +
> + rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, NULL);
> +
> + /* Test for errors in received frame */
> + if (status & BCOM_FEC_RX_BD_ERRORS) {
> + /* Drop packet and reuse the buffer */
> + bd = (struct bcom_fec_bd *)
> + bcom_prepare_next_buffer(priv->rx_dmatsk);
> +
> + bd->status = FEC_RX_BUFFER_SIZE;
> + bd->skb_pa = virt_to_phys(rskb->data);
> +
> + bcom_submit_next_buffer(priv->rx_dmatsk, rskb);
> +
> + priv->stats.rx_dropped++;
> +
> + continue;
> + }
> +
> + /* skbs are allocated on open, so now we allocate a new one,
> + * and remove the old (with the packet) */
> + skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
> + if (skb) {
> + /* Process the received skb */
> + int length = status & BCOM_FEC_RX_BD_LEN_MASK;
> +
> + skb_put(rskb, length - 4); /* length without CRC32 */
> +
> + rskb->dev = dev;
> + rskb->protocol = eth_type_trans(rskb, dev);
> +
> + netif_rx(rskb);
> + dev->last_rx = jiffies;
> + } else {
> + /* Can't get a new one : reuse the same & drop pkt */
> + dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
> + priv->stats.rx_dropped++;
> +
> + skb = rskb;
> + }
> +
> + bd = (struct bcom_fec_bd *)
> + bcom_prepare_next_buffer(priv->rx_dmatsk);
> +
> + bd->status = FEC_RX_BUFFER_SIZE;
> + bd->skb_pa = virt_to_phys(skb->data);
> +
> + bcom_submit_next_buffer(priv->rx_dmatsk, skb);
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t fec_interrupt(int irq, void *dev_id)
> +{
> + struct net_device *dev = dev_id;
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> + u32 ievent;
> +
> + ievent = in_be32(&fec->ievent);
> +
> + ievent &= ~FEC_IEVENT_MII; /* mii is handled separately */
> + if (!ievent)
> + return IRQ_NONE;
> +
> + out_be32(&fec->ievent, ievent); /* clear pending events */
> +
> + if (ievent & ~(FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
> + if (ievent & ~FEC_IEVENT_TFINT)
> + dev_dbg(&dev->dev, "ievent: %08x\n", ievent);
> + return IRQ_HANDLED;
> + }
> +
> + if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
> + dev_warn(&dev->dev, "FEC_IEVENT_RFIFO_ERROR\n");
> + if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
> + dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
> +
> + fec_stop(dev);
> + fec_hw_init(dev);
> + fec_start(dev);
> +
> + netif_wake_queue(dev);
> + return IRQ_HANDLED;
> +}
> +
> +/*
> + * Get the current statistics.
> + * This may be called with the card open or closed.
> + */
> +static struct net_device_stats *fec_get_stats(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct net_device_stats *stats = &priv->stats;
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> +/* printk(KERN_ALERT "%s: %i, rmon_r_octets: %i, rmon_r_packets: %i, "
> + "ieee_r_octets_ok: %i, ieee_r_frame_ok: %i, "
> + "%i\n",
> + __func__, __LINE__,
> + in_be32(&fec->rmon_r_octets), in_be32(&fec->rmon_r_packets),
> + in_be32(&fec->ieee_r_octets_ok), in_be32(&fec->ieee_r_frame_ok),
> + 0);
> +*/
> + stats->rx_bytes = in_be32(&fec->rmon_r_octets);
> + stats->rx_packets = in_be32(&fec->rmon_r_packets);
> + stats->rx_errors = in_be32(&fec->rmon_r_crc_align) +
> + in_be32(&fec->rmon_r_undersize) +
> + in_be32(&fec->rmon_r_oversize) +
> + in_be32(&fec->rmon_r_frag) +
> + in_be32(&fec->rmon_r_jab);
> +
> + stats->tx_bytes = in_be32(&fec->rmon_t_octets);
> + stats->tx_packets = in_be32(&fec->rmon_t_packets);
> + stats->tx_errors = in_be32(&fec->rmon_t_crc_align) +
> + in_be32(&fec->rmon_t_undersize) +
> + in_be32(&fec->rmon_t_oversize) +
> + in_be32(&fec->rmon_t_frag) +
> + in_be32(&fec->rmon_t_jab);
> +
> + stats->multicast = in_be32(&fec->rmon_r_mc_pkt);
> + stats->collisions = in_be32(&fec->rmon_t_col);
> +
> + /* detailed rx_errors: */
> + stats->rx_length_errors = in_be32(&fec->rmon_r_undersize)
> + + in_be32(&fec->rmon_r_oversize)
> + + in_be32(&fec->rmon_r_frag)
> + + in_be32(&fec->rmon_r_jab);
> + stats->rx_over_errors = in_be32(&fec->r_macerr);
> + stats->rx_crc_errors = in_be32(&fec->ieee_r_crc);
> + stats->rx_frame_errors = in_be32(&fec->ieee_r_align);
> + stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop);
> + stats->rx_missed_errors = in_be32(&fec->rmon_r_drop);
> +
> + /* detailed tx_errors: */
> + stats->tx_aborted_errors = 0;
> + stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr);
> + stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop);
> + stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe);
> + stats->tx_window_errors = in_be32(&fec->ieee_t_lcol);
> +
> + return stats;
> +}
> +
> +/*
> + * Read MIB counters in order to reset them,
> + * then zero all the stats fields in memory
> + */
> +static void fec_reset_stats(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> +
> + out_be32(&fec->mib_control, FEC_MIB_DISABLE);
> + memset_io(&fec->rmon_t_drop, 0,
> + (u32)&fec->reserved10 - (u32)&fec->rmon_t_drop);
> + out_be32(&fec->mib_control, 0);
> +
> + memset(&priv->stats, 0, sizeof(priv->stats));
> +}
> +
> +/*
> + * Set or clear the multicast filter for this adaptor.
> + */
> +static void fec_set_multicast_list(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> + u32 rx_control;
> +
> + rx_control = in_be32(&fec->r_cntrl);
> +
> + if (dev->flags & IFF_PROMISC) {
> + rx_control |= FEC_RCNTRL_PROM;
> + out_be32(&fec->r_cntrl, rx_control);
> + } else {
> + rx_control &= ~FEC_RCNTRL_PROM;
> + out_be32(&fec->r_cntrl, rx_control);
> +
> + if (dev->flags & IFF_ALLMULTI) {
> + out_be32(&fec->gaddr1, 0xffffffff);
> + out_be32(&fec->gaddr2, 0xffffffff);
> + } else {
> + u32 crc;
> + int i;
> + struct dev_mc_list *dmi;
> + u32 gaddr1 = 0x00000000;
> + u32 gaddr2 = 0x00000000;
> +
> + dmi = dev->mc_list;
> + for (i=0; i<dev->mc_count; i++) {
> + crc = ether_crc_le(6, dmi->dmi_addr) >> 26;
> + if (crc >= 32)
> + gaddr1 |= 1 << (crc-32);
> + else
> + gaddr2 |= 1 << crc;
> + dmi = dmi->next;
> + }
> + out_be32(&fec->gaddr1, gaddr1);
> + out_be32(&fec->gaddr2, gaddr2);
> + }
> + }
> +}
> +
> +static void __init fec_str2mac(char *str, unsigned char *mac)
> +{
> + int i;
> + u64 val64;
> +
> + val64 = simple_strtoull(str, NULL, 16);
> +
> + for (i = 0; i < 6; i++)
> + mac[5-i] = val64 >> (i*8);
> +}
> +
> +static int __init mpc52xx_fec_mac_setup(char *mac_address)
> +{
> + fec_str2mac(mac_address, mpc52xx_fec_mac_addr);
> + return 0;
> +}
> +
> +/* XXX do we need this? */
> +__setup("mpc52xx-mac=", mpc52xx_fec_mac_setup);
> +
> +/**
> + * fec_hw_init
> + * @dev: network device
> + *
> + * Setup various hardware setting, only needed once on start
> + */
> +static void fec_hw_init(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> + int i;
> +
> + /* Whack a reset. We should wait for this. */
> + out_be32(&fec->ecntrl, FEC_ECNTRL_RESET);
> + for (i = 0; i < FEC_RESET_DELAY; ++i) {
> + if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0)
> + break;
> + udelay(1);
> + }
> + if (i == FEC_RESET_DELAY)
> + dev_err(&dev->dev, "FEC Reset timeout!\n");
> +
> + /* set pause to 0x20 frames */
> + out_be32(&fec->op_pause, FEC_OP_PAUSE_OPCODE | 0x20);
> +
> + /* high service request will be deasserted when there's < 7 bytes in fifo
> + * low service request will be deasserted when there's < 4*7 bytes in fifo
> + */
> + out_be32(&fec->rfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
> + out_be32(&fec->tfifo_cntrl, FEC_FIFO_CNTRL_FRAME | FEC_FIFO_CNTRL_LTG_7);
> +
> + /* alarm when <= x bytes in FIFO */
> + out_be32(&fec->rfifo_alarm, 0x0000030c);
> + out_be32(&fec->tfifo_alarm, 0x00000100);
> +
> + /* begin transmittion when 256 bytes are in FIFO (or EOF or FIFO full) */
> + out_be32(&fec->x_wmrk, FEC_FIFO_WMRK_256B);
> +
> + /* enable crc generation */
> + out_be32(&fec->xmit_fsm, FEC_XMIT_FSM_APPEND_CRC | FEC_XMIT_FSM_ENABLE_CRC);
> + out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */
> + out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */
> +
> + /* set phy speed and enable MII interrupt
> + * this can't be done in phy driver, since it needs to be called
> + * before fec stuff (even on resume) */
> + set_phy_speed(fec, priv->phy_speed);
> + out_be32(&fec->imask, in_be32(&fec->imask) | FEC_IMASK_MII);
> +}
> +
> +/**
> + * fec_start
> + * @dev: network device
> + *
> + * This function is called to start or restart the FEC during a link
> + * change. This happens on fifo errors or when switching between half
> + * and full duplex.
> + */
> +static void fec_start(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> + u32 rcntrl;
> + u32 tcntrl;
> + u32 tmp;
> +
> + /* clear sticky error bits */
> + tmp = FEC_FIFO_STATUS_ERR | FEC_FIFO_STATUS_UF | FEC_FIFO_STATUS_OF;
> + out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & tmp);
> + out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & tmp);
> +
> + /* FIFOs will reset on fec_enable */
> + out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_ENABLE_IS_RESET);
> +
> + /* Set station address. */
> + fec_set_paddr(dev, dev->dev_addr);
> +
> + fec_set_multicast_list(dev);
> +
> + /* set max frame len, enable flow control, select mii mode */
> + rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */
> + rcntrl |= FEC_RCNTRL_FCE;
> + rcntrl |= MII_RCNTL_MODE;
> + if (priv->duplex == DUPLEX_FULL)
> + tcntrl = FEC_TCNTRL_FDEN; /* FD enable */
> + else {
> + rcntrl |= FEC_RCNTRL_DRT; /* disable Rx on Tx (HD) */
> + tcntrl = 0;
> + }
> + out_be32(&fec->r_cntrl, rcntrl);
> + out_be32(&fec->x_cntrl, tcntrl);
> +
> + /* Clear any outstanding interrupt. */
> + out_be32(&fec->ievent, 0xffffffff);
> +
> + /* Enable interrupts we wish to service. */
> + out_be32(&fec->imask, FEC_IMASK_ENABLE);
> +
> + /* And last, enable the transmit and receive processing. */
> + out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN);
> + out_be32(&fec->r_des_active, 0x01000000);
> +
> + priv->tx_full = 0;
> +}
> +
> +/**
> + * fec_stop
> + * @dev: network device
> + *
> + * stop all activity on fec and empty dma buffers
> + */
> +static void fec_stop(struct net_device *dev)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mpc52xx_fec __iomem *fec = priv->fec;
> + unsigned long timeout;
> +
> + out_be32(&fec->imask, FEC_IMASK_MII); /* disable all but MII interrupt */
> +
> + /* Disable the rx and tx tasks. */
> + bcom_disable(priv->rx_dmatsk);
> +
> + /* Wait for queues to drain, but only if we're in process context */
> + if (!in_interrupt()) {
> + timeout = jiffies + 2*HZ;
> + while (time_before(jiffies, timeout) &&
> + (!bcom_queue_empty(priv->tx_dmatsk) ||
> + !bcom_queue_empty(priv->rx_dmatsk))) {
> + set_current_state(TASK_INTERRUPTIBLE);
> + schedule_timeout(HZ/10);
> + }
> + if (time_after_eq(jiffies, timeout))
> + dev_err(&dev->dev, "queues didn't drain\n");
> + }
> +
> + bcom_disable(priv->tx_dmatsk);
> +
> + /* Stop FEC */
> + out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN);
> +
> + return;
> +}
> +
> +static int fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> +{
> + struct fec_priv *priv = netdev_priv(dev);
> + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
> +
> + return phy_mii_ioctl(priv->phydev, mii, cmd);
> +}
> +
> +/* ======================================================================== */
> +/* OF Driver */
> +/* ======================================================================== */
> +
> +static int __devinit
> +mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
> +{
> + int rv;
> + struct net_device *ndev;
> + struct fec_priv *priv = NULL;
> + struct resource mem;
> +
> + phys_addr_t rx_fifo;
> + phys_addr_t tx_fifo;
> +
> + /* Get the ether ndev & it's private zone */
> + ndev = alloc_etherdev(sizeof(struct fec_priv));
> + if (!ndev)
> + return -ENOMEM;
> +
> + priv = netdev_priv(ndev);
> +
> + priv->ofdev = op;
> +
> + /* Reserve FEC control zone */
> + rv = of_address_to_resource(op->node, 0, &mem);
> + if (rv) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "Error while parsing device node resource\n" );
> + return rv;
> + }
> + if ((mem.end - mem.start + 1) != sizeof(struct mpc52xx_fec)) {
> + printk(KERN_ERR DRIVER_NAME
> + " - invalid resource size (%lx != %x), check mpc52xx_devices.c\n",
> + (unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec));
> + return -EINVAL;
> + }
> +
> + if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec), DRIVER_NAME))
> + return -EBUSY;
> +
> + /* Init ether ndev with what we have */
> + ndev->open = fec_open;
> + ndev->stop = fec_close;
> + ndev->hard_start_xmit = fec_hard_start_xmit;
> + ndev->do_ioctl = fec_ioctl;
> + ndev->get_stats = fec_get_stats;
> + ndev->set_mac_address = fec_set_mac_address;
> + ndev->set_multicast_list = fec_set_multicast_list;
> + ndev->tx_timeout = fec_tx_timeout;
> + ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT;
> + ndev->flags &= ~IFF_RUNNING;
> + ndev->base_addr = mem.start;
> +
> + priv->t_irq = priv->r_irq = ndev->irq = NO_IRQ; /* IRQ are free for now */
> +
> + spin_lock_init(&priv->lock);
> +
> + /* ioremap the zones */
> + priv->fec = ioremap(mem.start, sizeof(struct mpc52xx_fec));
> +
> + if (!priv->fec) {
> + rv = -ENOMEM;
> + goto probe_error;
> + }
> +
> + /* Bestcomm init */
> + rx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, rfifo_data);
> + tx_fifo = ndev->base_addr + offsetof(struct mpc52xx_fec, tfifo_data);
> +
> + priv->rx_dmatsk = bcom_fec_rx_init(FEC_RX_NUM_BD, rx_fifo, FEC_RX_BUFFER_SIZE);
> + priv->tx_dmatsk = bcom_fec_tx_init(FEC_TX_NUM_BD, tx_fifo);
> +
> + if (!priv->rx_dmatsk || !priv->tx_dmatsk) {
> + printk(KERN_ERR DRIVER_NAME ": Can not init SDMA tasks\n" );
> + rv = -ENOMEM;
> + goto probe_error;
> + }
> +
> + /* Get the IRQ we need one by one */
> + /* Control */
> + ndev->irq = irq_of_parse_and_map(op->node, 0);
> +
> + /* RX */
> + priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk);
> +
> + /* TX */
> + priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk);
> +
> + /* MAC address init */
> + if (memcmp(mpc52xx_fec_mac_addr, null_mac, 6) != 0)
> + memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
> + else
> + fec_get_paddr(ndev, ndev->dev_addr);
> +
> + /* Phy speed */
> + priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
> +
> + priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
> + priv->duplex = DUPLEX_HALF;
> +
> + /* Hardware init */
> + fec_hw_init(ndev);
> +
> + fec_reset_stats(ndev);
> +
> + /* Register the new network device */
> + rv = register_netdev(ndev);
> + if (rv < 0)
> + goto probe_error;
> +
> + /* We're done ! */
> + dev_set_drvdata(&op->dev, ndev);
> +
> + return 0;
> +
> +
> + /* Error handling - free everything that might be allocated */
> +probe_error:
> +
> + irq_dispose_mapping(ndev->irq);
> +
> + if (priv->rx_dmatsk)
> + bcom_fec_rx_release(priv->rx_dmatsk);
> + if (priv->tx_dmatsk)
> + bcom_fec_tx_release(priv->tx_dmatsk);
> +
> + if (priv->fec)
> + iounmap(priv->fec);
> +
> + release_mem_region(mem.start, sizeof(struct mpc52xx_fec));
> +
> + free_netdev(ndev);
> +
> + return rv;
> +}
> +
> +static int
> +mpc52xx_fec_remove(struct of_device *op)
> +{
> + struct net_device *ndev;
> + struct fec_priv *priv;
> +
> + ndev = dev_get_drvdata(&op->dev);
> + if (!ndev)
> + return 0;
> + priv = netdev_priv(ndev);
> +
> + unregister_netdev(ndev);
> +
> + irq_dispose_mapping(ndev->irq);
> +
> + bcom_fec_rx_release(priv->rx_dmatsk);
> + bcom_fec_tx_release(priv->tx_dmatsk);
> +
> + iounmap(priv->fec);
> +
> + release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec));
> +
> + free_netdev(ndev);
> +
> + dev_set_drvdata(&op->dev, NULL);
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state)
> +{
> + struct net_device *dev = dev_get_drvdata(&op->dev);
> +
> + if (netif_running(dev))
> + fec_close(dev);
> +
> + return 0;
> +}
> +
> +static int mpc52xx_fec_of_resume(struct of_device *op)
> +{
> + struct net_device *dev = dev_get_drvdata(&op->dev);
> +
> + fec_hw_init(dev);
> + fec_reset_stats(dev);
> +
> + if (netif_running(dev))
> + fec_open(dev);
> +
> + return 0;
> +}
> +#endif
> +
> +static struct of_device_id mpc52xx_fec_match[] = {
> + {
> + .type = "network",
> + .compatible = "mpc5200-fec",
> + },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(of, mpc52xx_fec_match);
> +
> +static struct of_platform_driver mpc52xx_fec_driver = {
> + .owner = THIS_MODULE,
> + .name = DRIVER_NAME,
> + .match_table = mpc52xx_fec_match,
> + .probe = mpc52xx_fec_probe,
> + .remove = mpc52xx_fec_remove,
> +#ifdef CONFIG_PM
> + .suspend = mpc52xx_fec_of_suspend,
> + .resume = mpc52xx_fec_of_resume,
> +#endif
> +};
> +
> +
> +/* ======================================================================== */
> +/* Module */
> +/* ======================================================================== */
> +
> +static int __init
> +mpc52xx_fec_init(void)
> +{
> + int ret;
> + if ((ret = fec_mdio_init())) {
Why not:
int ret = fec_mdio_init();
if (ret) {
Less parenthesis, looks more clear
> + printk(KERN_ERR "%s: %i fec_mdio_init failed\n", __func__, __LINE__);
> + return ret;
> + }
> +
> + return of_register_platform_driver(&mpc52xx_fec_driver);
> +}
> +
> +static void __exit
> +mpc52xx_fec_exit(void)
> +{
> + of_unregister_platform_driver(&mpc52xx_fec_driver);
> + fec_mdio_exit();
> +}
> +
> +
> +module_init(mpc52xx_fec_init);
> +module_exit(mpc52xx_fec_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Dale Farnsworth");
> +MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC");
> +
> diff -pruN dummy/fec.h ./drivers/net/fec_mpc52xx/fec.h
> --- dummy/fec.h 1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec.h 2007-08-10 11:24:37.000000000 +0200
> @@ -0,0 +1,299 @@
> +/*
> + * drivers/net/fec_mpc52xx/fec.h
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + *
> + * Author: Dale Farnsworth <dfarnsworth@mvista.com>
> + *
> + * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
> + * the terms of the GNU General Public License version 2. This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + */
> +
> +#ifndef __DRIVERS_NET_MPC52XX_FEC_H__
> +#define __DRIVERS_NET_MPC52XX_FEC_H__
> +
> +#include <linux/mii.h> // XXX, still needed?
> +#include <linux/phy.h>
> +
> +/* Tunable constant */
> +/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */
> +#define FEC_RX_BUFFER_SIZE 1522 /* max receive packet size */
> +#define FEC_RX_NUM_BD 64
> +#define FEC_TX_NUM_BD 64
> +
> +#define FEC_RESET_DELAY 50 /* uS */
> +
> +#define FEC_WATCHDOG_TIMEOUT ((400*HZ)/1000)
> +
> +struct fec_priv {
> + int duplex;
> + int tx_full;
> + int r_irq;
> + int t_irq;
> + struct mpc52xx_fec __iomem *fec;
> + struct bcom_task *rx_dmatsk;
> + struct bcom_task *tx_dmatsk;
> + spinlock_t lock;
> + struct net_device_stats stats;
> + int msg_enable;
> +#ifdef CONFIG_FEC_MPC52xx_MDIO
> + uint phy_speed;
> +
> + struct phy_device *phydev;
> + enum phy_state link;
> + int speed;
> +
> + struct of_device *ofdev;
> +#endif /* CONFIG_FEC_MPC52xx_MDIO */
> +};
> +
> +
> +/* ======================================================================== */
> +/* Hardware register sets & bits */
> +/* ======================================================================== */
> +
> +struct mpc52xx_fec {
> + u32 fec_id; /* FEC + 0x000 */
> + u32 ievent; /* FEC + 0x004 */
> + u32 imask; /* FEC + 0x008 */
> +
> + u32 reserved0[1]; /* FEC + 0x00C */
> + u32 r_des_active; /* FEC + 0x010 */
> + u32 x_des_active; /* FEC + 0x014 */
> + u32 r_des_active_cl; /* FEC + 0x018 */
> + u32 x_des_active_cl; /* FEC + 0x01C */
> + u32 ivent_set; /* FEC + 0x020 */
> + u32 ecntrl; /* FEC + 0x024 */
> +
> + u32 reserved1[6]; /* FEC + 0x028-03C */
> + u32 mii_data; /* FEC + 0x040 */
> + u32 mii_speed; /* FEC + 0x044 */
> + u32 mii_status; /* FEC + 0x048 */
> +
> + u32 reserved2[5]; /* FEC + 0x04C-05C */
> + u32 mib_data; /* FEC + 0x060 */
> + u32 mib_control; /* FEC + 0x064 */
> +
> + u32 reserved3[6]; /* FEC + 0x068-7C */
> + u32 r_activate; /* FEC + 0x080 */
> + u32 r_cntrl; /* FEC + 0x084 */
> + u32 r_hash; /* FEC + 0x088 */
> + u32 r_data; /* FEC + 0x08C */
> + u32 ar_done; /* FEC + 0x090 */
> + u32 r_test; /* FEC + 0x094 */
> + u32 r_mib; /* FEC + 0x098 */
> + u32 r_da_low; /* FEC + 0x09C */
> + u32 r_da_high; /* FEC + 0x0A0 */
> +
> + u32 reserved4[7]; /* FEC + 0x0A4-0BC */
> + u32 x_activate; /* FEC + 0x0C0 */
> + u32 x_cntrl; /* FEC + 0x0C4 */
> + u32 backoff; /* FEC + 0x0C8 */
> + u32 x_data; /* FEC + 0x0CC */
> + u32 x_status; /* FEC + 0x0D0 */
> + u32 x_mib; /* FEC + 0x0D4 */
> + u32 x_test; /* FEC + 0x0D8 */
> + u32 fdxfc_da1; /* FEC + 0x0DC */
> + u32 fdxfc_da2; /* FEC + 0x0E0 */
> + u32 paddr1; /* FEC + 0x0E4 */
> + u32 paddr2; /* FEC + 0x0E8 */
> + u32 op_pause; /* FEC + 0x0EC */
> +
> + u32 reserved5[4]; /* FEC + 0x0F0-0FC */
> + u32 instr_reg; /* FEC + 0x100 */
> + u32 context_reg; /* FEC + 0x104 */
> + u32 test_cntrl; /* FEC + 0x108 */
> + u32 acc_reg; /* FEC + 0x10C */
> + u32 ones; /* FEC + 0x110 */
> + u32 zeros; /* FEC + 0x114 */
> + u32 iaddr1; /* FEC + 0x118 */
> + u32 iaddr2; /* FEC + 0x11C */
> + u32 gaddr1; /* FEC + 0x120 */
> + u32 gaddr2; /* FEC + 0x124 */
> + u32 random; /* FEC + 0x128 */
> + u32 rand1; /* FEC + 0x12C */
> + u32 tmp; /* FEC + 0x130 */
> +
> + u32 reserved6[3]; /* FEC + 0x134-13C */
> + u32 fifo_id; /* FEC + 0x140 */
> + u32 x_wmrk; /* FEC + 0x144 */
> + u32 fcntrl; /* FEC + 0x148 */
> + u32 r_bound; /* FEC + 0x14C */
> + u32 r_fstart; /* FEC + 0x150 */
> + u32 r_count; /* FEC + 0x154 */
> + u32 r_lag; /* FEC + 0x158 */
> + u32 r_read; /* FEC + 0x15C */
> + u32 r_write; /* FEC + 0x160 */
> + u32 x_count; /* FEC + 0x164 */
> + u32 x_lag; /* FEC + 0x168 */
> + u32 x_retry; /* FEC + 0x16C */
> + u32 x_write; /* FEC + 0x170 */
> + u32 x_read; /* FEC + 0x174 */
> +
> + u32 reserved7[2]; /* FEC + 0x178-17C */
> + u32 fm_cntrl; /* FEC + 0x180 */
> + u32 rfifo_data; /* FEC + 0x184 */
> + u32 rfifo_status; /* FEC + 0x188 */
> + u32 rfifo_cntrl; /* FEC + 0x18C */
> + u32 rfifo_lrf_ptr; /* FEC + 0x190 */
> + u32 rfifo_lwf_ptr; /* FEC + 0x194 */
> + u32 rfifo_alarm; /* FEC + 0x198 */
> + u32 rfifo_rdptr; /* FEC + 0x19C */
> + u32 rfifo_wrptr; /* FEC + 0x1A0 */
> + u32 tfifo_data; /* FEC + 0x1A4 */
> + u32 tfifo_status; /* FEC + 0x1A8 */
> + u32 tfifo_cntrl; /* FEC + 0x1AC */
> + u32 tfifo_lrf_ptr; /* FEC + 0x1B0 */
> + u32 tfifo_lwf_ptr; /* FEC + 0x1B4 */
> + u32 tfifo_alarm; /* FEC + 0x1B8 */
> + u32 tfifo_rdptr; /* FEC + 0x1BC */
> + u32 tfifo_wrptr; /* FEC + 0x1C0 */
> +
> + u32 reset_cntrl; /* FEC + 0x1C4 */
> + u32 xmit_fsm; /* FEC + 0x1C8 */
> +
> + u32 reserved8[3]; /* FEC + 0x1CC-1D4 */
> + u32 rdes_data0; /* FEC + 0x1D8 */
> + u32 rdes_data1; /* FEC + 0x1DC */
> + u32 r_length; /* FEC + 0x1E0 */
> + u32 x_length; /* FEC + 0x1E4 */
> + u32 x_addr; /* FEC + 0x1E8 */
> + u32 cdes_data; /* FEC + 0x1EC */
> + u32 status; /* FEC + 0x1F0 */
> + u32 dma_control; /* FEC + 0x1F4 */
> + u32 des_cmnd; /* FEC + 0x1F8 */
> + u32 data; /* FEC + 0x1FC */
> +
> + u32 rmon_t_drop; /* FEC + 0x200 */
> + u32 rmon_t_packets; /* FEC + 0x204 */
> + u32 rmon_t_bc_pkt; /* FEC + 0x208 */
> + u32 rmon_t_mc_pkt; /* FEC + 0x20C */
> + u32 rmon_t_crc_align; /* FEC + 0x210 */
> + u32 rmon_t_undersize; /* FEC + 0x214 */
> + u32 rmon_t_oversize; /* FEC + 0x218 */
> + u32 rmon_t_frag; /* FEC + 0x21C */
> + u32 rmon_t_jab; /* FEC + 0x220 */
> + u32 rmon_t_col; /* FEC + 0x224 */
> + u32 rmon_t_p64; /* FEC + 0x228 */
> + u32 rmon_t_p65to127; /* FEC + 0x22C */
> + u32 rmon_t_p128to255; /* FEC + 0x230 */
> + u32 rmon_t_p256to511; /* FEC + 0x234 */
> + u32 rmon_t_p512to1023; /* FEC + 0x238 */
> + u32 rmon_t_p1024to2047; /* FEC + 0x23C */
> + u32 rmon_t_p_gte2048; /* FEC + 0x240 */
> + u32 rmon_t_octets; /* FEC + 0x244 */
> + u32 ieee_t_drop; /* FEC + 0x248 */
> + u32 ieee_t_frame_ok; /* FEC + 0x24C */
> + u32 ieee_t_1col; /* FEC + 0x250 */
> + u32 ieee_t_mcol; /* FEC + 0x254 */
> + u32 ieee_t_def; /* FEC + 0x258 */
> + u32 ieee_t_lcol; /* FEC + 0x25C */
> + u32 ieee_t_excol; /* FEC + 0x260 */
> + u32 ieee_t_macerr; /* FEC + 0x264 */
> + u32 ieee_t_cserr; /* FEC + 0x268 */
> + u32 ieee_t_sqe; /* FEC + 0x26C */
> + u32 t_fdxfc; /* FEC + 0x270 */
> + u32 ieee_t_octets_ok; /* FEC + 0x274 */
> +
> + u32 reserved9[2]; /* FEC + 0x278-27C */
> + u32 rmon_r_drop; /* FEC + 0x280 */
> + u32 rmon_r_packets; /* FEC + 0x284 */
> + u32 rmon_r_bc_pkt; /* FEC + 0x288 */
> + u32 rmon_r_mc_pkt; /* FEC + 0x28C */
> + u32 rmon_r_crc_align; /* FEC + 0x290 */
> + u32 rmon_r_undersize; /* FEC + 0x294 */
> + u32 rmon_r_oversize; /* FEC + 0x298 */
> + u32 rmon_r_frag; /* FEC + 0x29C */
> + u32 rmon_r_jab; /* FEC + 0x2A0 */
> +
> + u32 rmon_r_resvd_0; /* FEC + 0x2A4 */
> +
> + u32 rmon_r_p64; /* FEC + 0x2A8 */
> + u32 rmon_r_p65to127; /* FEC + 0x2AC */
> + u32 rmon_r_p128to255; /* FEC + 0x2B0 */
> + u32 rmon_r_p256to511; /* FEC + 0x2B4 */
> + u32 rmon_r_p512to1023; /* FEC + 0x2B8 */
> + u32 rmon_r_p1024to2047; /* FEC + 0x2BC */
> + u32 rmon_r_p_gte2048; /* FEC + 0x2C0 */
> + u32 rmon_r_octets; /* FEC + 0x2C4 */
> + u32 ieee_r_drop; /* FEC + 0x2C8 */
> + u32 ieee_r_frame_ok; /* FEC + 0x2CC */
> + u32 ieee_r_crc; /* FEC + 0x2D0 */
> + u32 ieee_r_align; /* FEC + 0x2D4 */
> + u32 r_macerr; /* FEC + 0x2D8 */
> + u32 r_fdxfc; /* FEC + 0x2DC */
> + u32 ieee_r_octets_ok; /* FEC + 0x2E0 */
> +
> + u32 reserved10[7]; /* FEC + 0x2E4-2FC */
> +
> + u32 reserved11[64]; /* FEC + 0x300-3FF */
> +};
> +
> +#define FEC_MIB_DISABLE 0x80000000
> +
> +#define FEC_IEVENT_HBERR 0x80000000
> +#define FEC_IEVENT_BABR 0x40000000
> +#define FEC_IEVENT_BABT 0x20000000
> +#define FEC_IEVENT_GRA 0x10000000
> +#define FEC_IEVENT_TFINT 0x08000000
> +#define FEC_IEVENT_MII 0x00800000
> +#define FEC_IEVENT_LATE_COL 0x00200000
> +#define FEC_IEVENT_COL_RETRY_LIM 0x00100000
> +#define FEC_IEVENT_XFIFO_UN 0x00080000
> +#define FEC_IEVENT_XFIFO_ERROR 0x00040000
> +#define FEC_IEVENT_RFIFO_ERROR 0x00020000
> +
> +#define FEC_IMASK_HBERR 0x80000000
> +#define FEC_IMASK_BABR 0x40000000
> +#define FEC_IMASK_BABT 0x20000000
> +#define FEC_IMASK_GRA 0x10000000
> +#define FEC_IMASK_MII 0x00800000
> +#define FEC_IMASK_LATE_COL 0x00200000
> +#define FEC_IMASK_COL_RETRY_LIM 0x00100000
> +#define FEC_IMASK_XFIFO_UN 0x00080000
> +#define FEC_IMASK_XFIFO_ERROR 0x00040000
> +#define FEC_IMASK_RFIFO_ERROR 0x00020000
> +
> +#define FEC_RCNTRL_MAX_FL_SHIFT 16
> +#define FEC_RCNTRL_LOOP 0x01
> +#define FEC_RCNTRL_DRT 0x02
> +#define FEC_RCNTRL_MII_MODE 0x04
> +#define FEC_RCNTRL_PROM 0x08
> +#define FEC_RCNTRL_BC_REJ 0x10
> +#define FEC_RCNTRL_FCE 0x20
> +
> +#define FEC_TCNTRL_GTS 0x00000001
> +#define FEC_TCNTRL_HBC 0x00000002
> +#define FEC_TCNTRL_FDEN 0x00000004
> +#define FEC_TCNTRL_TFC_PAUSE 0x00000008
> +#define FEC_TCNTRL_RFC_PAUSE 0x00000010
> +
> +#define FEC_ECNTRL_RESET 0x00000001
> +#define FEC_ECNTRL_ETHER_EN 0x00000002
> +
> +#define FEC_PADDR2_TYPE 0x8808
> +
> +#define FEC_OP_PAUSE_OPCODE 0x00010000
> +
> +#define FEC_FIFO_WMRK_256B 0x3
> +
> +#define FEC_FIFO_STATUS_ERR 0x00400000
> +#define FEC_FIFO_STATUS_UF 0x00200000
> +#define FEC_FIFO_STATUS_OF 0x00100000
> +
> +#define FEC_FIFO_CNTRL_FRAME 0x08000000
> +#define FEC_FIFO_CNTRL_LTG_7 0x07000000
> +
> +#define FEC_RESET_CNTRL_RESET_FIFO 0x02000000
> +#define FEC_RESET_CNTRL_ENABLE_IS_RESET 0x01000000
> +
> +#define FEC_XMIT_FSM_APPEND_CRC 0x02000000
> +#define FEC_XMIT_FSM_ENABLE_CRC 0x01000000
> +
> +
> +int __init fec_mdio_init(void);
> +void __exit fec_mdio_exit(void);
> +
> +#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */
> diff -pruN dummy/fec_phy.c ./drivers/net/fec_mpc52xx/fec_phy.c
> --- dummy/fec_phy.c 1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec_phy.c 2007-08-10 10:59:53.000000000 +0200
> @@ -0,0 +1,229 @@
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/phy.h>
> +#include <asm/io.h>
> +#include <asm/mpc52xx.h>
> +#include <asm/of_platform.h>
> +#include "fec_phy.h"
> +#include "fec.h"
> +
> +struct fec_mdio_priv {
> + int completed;
> + wait_queue_head_t wq;
> + struct mpc52xx_fec __iomem *regs;
> + int irq;
> +};
> +
> +static int fec_mdio_read(struct mii_bus *bus, int phy_id, int reg)
> +{
> + struct fec_mdio_priv *priv = bus->priv;
> + int tries = 100;
> +
> + u32 request = FEC_MII_READ_FRAME;
> + request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
> + request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
> +
> + out_be32(&priv->regs->mii_data, request);
> +
> + /* wait for it to finish, this takes about 23 us on lite5200b */
> + while (priv->completed == 0 && tries--)
> + udelay(5);
> +
> + priv->completed = 0;
> +
> + if (tries == 0)
> + return -ETIMEDOUT;
> +
> + return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK;
> +}
> +
> +static int fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
> +{
> + struct fec_mdio_priv *priv = bus->priv;
> + u32 value = data;
> + int tries = 100;
> +
> + value |= FEC_MII_WRITE_FRAME;
> + value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
> + value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
> +
> + out_be32(&priv->regs->mii_data, value);
> +
> + /* wait for request to finish */
> + while (priv->completed == 0 && tries--)
> + udelay(5);
> +
> + priv->completed = 0;
> +
> + if (tries == 0)
> + return -ETIMEDOUT;
> +
> + return 0;
> +}
> +
> +static irqreturn_t fec_mdio_interrupt(int irq, void *dev_id)
> +{
> + struct fec_mdio_priv *priv = dev_id;
> + struct mpc52xx_fec __iomem *fec;
> + int ievent;
> +
> + fec = priv->regs;
> + ievent = in_be32(&fec->ievent);
> +
> + ievent &= FEC_IEVENT_MII;
> + if (!ievent)
> + return IRQ_NONE;
> +
> + out_be32(&fec->ievent, ievent);
> +
> + priv->completed = 1;
> + wake_up(&priv->wq);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int fec_mdio_probe(struct of_device *of, const struct of_device_id *match)
> +{
> + struct device *dev = &of->dev;
> + struct device_node *np = of->node;
> + struct device_node *child = NULL;
> + struct mii_bus *bus;
> + struct fec_mdio_priv *priv;
> + struct resource res = {};
> + int err;
> + int i;
> +
> + bus = kzalloc(sizeof(*bus), GFP_KERNEL);
> + if (bus == NULL)
> + return -ENOMEM;
> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> + if (priv == NULL) {
> + err = -ENOMEM;
> + goto out_free;
> + }
> +
> + bus->name = "mpc52xx MII bus";
> + bus->read = fec_mdio_read;
> + bus->write = fec_mdio_write;
> +
> + /* setup irqs */
> + bus->irq = kcalloc(sizeof(bus->irq[0]), PHY_MAX_ADDR, GFP_KERNEL);
> + if (bus->irq == NULL) {
> + err = -ENOMEM;
> + goto out_free;
> + }
> + for (i=0; i<PHY_MAX_ADDR; i++)
> + bus->irq[i] = PHY_POLL;
> +
> + while ((child = of_get_next_child(np, child)) != NULL) {
> + int irq = irq_of_parse_and_map(child, 0);
> + if (irq != NO_IRQ) {
> + const u32 *id = of_get_property(child, "reg", NULL);
> + bus->irq[*id] = irq;
> + }
> + }
> +
> + /* setup registers */
> + err = of_address_to_resource(np, 0, &res);
> + if (err)
> + goto out_free;
> + priv->regs = ioremap(res.start, res.end - res.start + 1);
> + if (priv->regs == NULL) {
> + err = -ENOMEM;
> + goto out_free;
> + }
> +
> + priv->irq = irq_of_parse_and_map(np, 0);
> + err = request_irq(priv->irq, &fec_mdio_interrupt, IRQF_DISABLED | IRQF_SHARED,
> + "fec_mdio", priv);
> + if (err) {
> + printk(KERN_ERR "%s: interrupt request failed with %i\n", __func__, err);
> + goto out_unmap;
> + }
> +
> + bus->id = res.start;
> + bus->priv = priv;
> +
> + bus->dev = dev;
> + dev_set_drvdata(dev, bus);
> +
> + init_waitqueue_head(&priv->wq);
> +
> + /* set MII speed */
> + out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
> +
> + /* enable MII interrupt */
> + out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII);
> +
> + err = mdiobus_register(bus);
> + if (err)
> + goto out_free_irq;
> +
> + return 0;
> +
> + out_free_irq:
> + free_irq(priv->irq, dev);
> + irq_dispose_mapping(priv->irq);
> + out_unmap:
> + iounmap(priv->regs);
> + out_free:
> + for (i=0; i<PHY_MAX_ADDR; i++)
> + if (bus->irq[i])
> + irq_dispose_mapping(bus->irq[i]);
> + kfree(bus->irq);
> + kfree(priv);
> + kfree(bus);
> +
> + return err;
> +}
> +
> +static int fec_mdio_remove(struct of_device *of)
> +{
> + struct device *dev = &of->dev;
> + struct mii_bus *bus = dev_get_drvdata(dev);
> + struct fec_mdio_priv *priv = bus->priv;
> + int i;
> +
> + mdiobus_unregister(bus);
> + dev_set_drvdata(dev, NULL);
> +
> + free_irq(priv->irq, dev);
> + irq_dispose_mapping(priv->irq);
> + iounmap(priv->regs);
> + for (i=0; i<PHY_MAX_ADDR; i++)
> + if (bus->irq[i])
> + irq_dispose_mapping(bus->irq[i]);
> + kfree(priv);
> + kfree(bus->irq);
> + kfree(bus);
> +
> + return 0;
> +}
> +
> +
> +static struct of_device_id fec_mdio_match[] = {
> + {
> + .type = "mdio",
> + .compatible = "mpc5200b-fec-phy",
> + },
> + {},
> +};
> +
> +static struct of_platform_driver fec_mdio_driver = {
> + .name = "mpc5200b-fec-phy",
> + .probe = fec_mdio_probe,
> + .remove = fec_mdio_remove,
> + .match_table = fec_mdio_match,
> +};
> +
> +
> +int __init fec_mdio_init(void)
> +{
> + return of_register_platform_driver(&fec_mdio_driver);
> +}
> +
> +void __exit fec_mdio_exit(void)
> +{
> + of_unregister_platform_driver(&fec_mdio_driver);
> +}
> diff -pruN dummy/fec_phy.h ./drivers/net/fec_mpc52xx/fec_phy.h
> --- dummy/fec_phy.h 1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/fec_phy.h 2007-08-10 11:22:54.000000000 +0200
> @@ -0,0 +1,49 @@
> +/*
> + * arch/ppc/52xx_io/fec_phy.h
> + *
> + * Driver for the MPC5200 Fast Ethernet Controller
> + * Based heavily on the MII support for the MPC8xx by Dan Malek
> + *
> + * Author: Dale Farnsworth <dfarnsworth@mvista.com>
> + *
> + * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
> + * the terms of the GNU General Public License version 2. This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + */
> +
> +#define FEC_IMASK_ALL (FEC_IMASK_HBERR | FEC_IMASK_BABR | \
> + FEC_IMASK_BABT | FEC_IMASK_GRA | FEC_IMASK_MII | \
> + FEC_IMASK_LATE_COL | FEC_IMASK_COL_RETRY_LIM | \
> + FEC_IMASK_XFIFO_UN | FEC_IMASK_XFIFO_ERROR | \
> + FEC_IMASK_RFIFO_ERROR)
> +
> +#ifdef CONFIG_FEC_MPC52xx_MDIO
> +#define MII_RCNTL_MODE FEC_RCNTRL_MII_MODE
> +#define FEC_IMASK_ENABLE FEC_IMASK_ALL
> +#define set_phy_speed(fec, s) out_be32(&fec->mii_speed, s)
> +#else
> +#define MII_RCNTL_MODE 0
> +#define FEC_IMASK_ENABLE (FEC_IMASK_ALL & ~FEC_IMASK_MII)
> +#define set_phy_speed(fec, s) do { } while (0)
> +#define fec_mii_start(dev) do { } while (0)
> +#define fec_mii(dev) printk(KERN_WARNING "unexpected FEC_IEVENT_MII\n")
> +#define fec_mii_init(dev) do { } while (0)
> +#define fec_mii_suspend(dev) do { } while (0)
> +#define fec_mii_resume(dev) do { } while (0)
> +#endif /* CONFIG_FEC_MPC52xx_MDIO */
> +
> +/* MII-related definitions */
> +#define FEC_MII_DATA_ST 0x40000000 /* Start frame */
> +#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform read */
> +#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform write */
> +#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address mask */
> +#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register mask */
> +#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
> +#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data mask */
> +
> +#define FEC_MII_READ_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA)
> +#define FEC_MII_WRITE_FRAME (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | FEC_MII_DATA_TA)
> +
> +#define FEC_MII_DATA_RA_SHIFT 0x12 /* MII reg addr bits */
> +#define FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY addr bits */
> diff -pruN dummy/Kconfig ./drivers/net/fec_mpc52xx/Kconfig
> --- dummy/Kconfig 1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/Kconfig 2007-08-08 10:50:04.000000000 +0200
> @@ -0,0 +1,24 @@
> +menu "MPC5200 Networking Options"
> + depends PPC_MPC52xx && NET_ETHERNET
> +
> +config FEC_MPC52xx
> + tristate "FEC Ethernet"
> + depends on NET_ETHERNET
> + select PPC_BESTCOMM
> + select PPC_BESTCOMM_FEC
> + select CRC32
> + ---help---
> + This option enables support for the MPC5200's on-chip
> + Fast Ethernet Controller
> +
> +config USE_MDIO
> + bool "Use external Ethernet MII PHY"
> + select MII
> + depends FEC_MPC52xx
> + ---help---
> + The MPC5200's FEC can connect to the Ethernet either with
> + an external MII PHY chip or 10 Mbps 7-wire interface
> + (Motorola? industry standard).
> + If your board uses an external PHY, say y, else n.
> +
> +endmenu
> diff -pruN dummy/Makefile ./drivers/net/fec_mpc52xx/Makefile
> --- dummy/Makefile 1970-01-01 01:00:00.000000000 +0100
> +++ ./drivers/net/fec_mpc52xx/Makefile 2007-08-08 10:50:04.000000000 +0200
> @@ -0,0 +1,7 @@
> +obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
> +
> +fec_mpc52xx-objs := fec.o
> +
> +ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
> +fec_mpc52xx-objs += fec_phy.o
> +endif
> Index: work-powerpc.git/arch/powerpc/boot/dts/lite5200b.dts
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/boot/dts/lite5200b.dts
> +++ work-powerpc.git/arch/powerpc/boot/dts/lite5200b.dts
> @@ -365,10 +365,26 @@
> ethernet@3000 {
> device_type = "network";
> compatible = "mpc5200b-fec\0mpc5200-fec";
> - reg = <3000 800>;
> + reg = <3000 400>;
> mac-address = [ 02 03 04 05 06 07 ]; // Bad!
> interrupts = <2 5 0>;
> interrupt-parent = <&mpc5200_pic>;
> + phy-handle = <&phy0>;
> + };
> +
> + mdio@3000 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + device_type = "mdio";
> + compatible = "mpc5200b-fec-phy";
> + reg = <3000 400>; // fec range, since we need to setup fec interrupts
> + interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
> + interrupt-parent = <&mpc5200_pic>;
> +
> + phy0:ethernet-phy@0 {
> + device_type = "ethernet-phy";
> + reg = <0>;
> + };
> };
>
> ata@3a00 {
> Index: work-powerpc.git/arch/powerpc/sysdev/bestcomm/fec.h
> ===================================================================
> --- work-powerpc.git.orig/arch/powerpc/sysdev/bestcomm/fec.h
> +++ work-powerpc.git/arch/powerpc/sysdev/bestcomm/fec.h
> @@ -22,6 +22,20 @@ struct bcom_fec_bd {
>
> #define BCOM_FEC_TX_BD_TFD 0x08000000ul /* transmit frame done */
> #define BCOM_FEC_TX_BD_INT 0x04000000ul /* interrupt */
> +#define BCOM_FEC_TX_BD_TC 0x04000000ul /* transmit CRC XXX same as ^? */
> +#define BCOM_FEC_TX_BD_ABC 0x02000000ul /* append bad CRC */
> +
> +#define BCOM_FEC_RX_BD_L 0x08000000ul /* buffer is last in frame */
> +#define BCOM_FEC_RX_BD_BC 0x00800000ul /* DA is broadcast */
> +#define BCOM_FEC_RX_BD_MC 0x00400000ul /* DA is multicast and not broadcast */
> +#define BCOM_FEC_RX_BD_LG 0x00200000ul /* Rx frame length violation */
> +#define BCOM_FEC_RX_BD_NO 0x00100000ul /* Rx non-octet aligned frame */
> +#define BCOM_FEC_RX_BD_CR 0x00040000ul /* Rx CRC error */
> +#define BCOM_FEC_RX_BD_OV 0x00020000ul /* overrun */
> +#define BCOM_FEC_RX_BD_TR 0x00010000ul /* Rx frame truncated */
> +#define BCOM_FEC_RX_BD_LEN_MASK 0x000007fful /* mask for length of received frame */
> +#define BCOM_FEC_RX_BD_ERRORS (BCOM_FEC_RX_BD_LG | BCOM_FEC_RX_BD_NO | \
> + BCOM_FEC_RX_BD_CR | BCOM_FEC_RX_BD_OV | BCOM_FEC_RX_BD_TR)
>
>
> extern struct bcom_task *
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Kernel oops report
From: Jesper Juhl @ 2007-08-10 13:18 UTC (permalink / raw)
To: Sinisa Segvic; +Cc: linux-kernel, Netdev
In-Reply-To: <20070810122614.zm7yplmk0skgg080@webmail.tugraz.at>
(this one looks like it should go to netdev as well - added to Cc)
On 10/08/07, Sinisa Segvic <sinisa.segvic@tugraz.at> wrote:
> Hi,
>
> I've just got a kernel oops.
>
> http://lxr.linux.no/source/Documentation/oops-tracing.txt
> seems to suggest that oops reports are welcome at this address.
>
> Cheers,
>
> Sinisa
>
> $ uname -a
> Linux PCs129.EMT.tugraz.at 2.6.20-16-386 #2 Thu Jun 7 20:16:13 UTC
> 2007 i686 GNU/Linux
>
>
>
> [326735.692443] BUG: unable to handle kernel NULL pointer dereference
> at virtual address 0000001b
> [326735.692454] printing eip:
> [326735.692457] c015f581
> [326735.692458] *pde = 00000000
> [326735.692463] Oops: 0000 [#1]
> [326735.692466] Modules linked in: nls_cp437 isofs udf binfmt_misc
> rfcomm l2cap bluetooth nfs lockd sunrpc xt_limit xt_tcpudp
> iptable_mangle ipt_LOG ipt_MASQUERADE nf_nat ipt_TOS ipt_REJECT
> nf_conntrack_irc nf_conntrack_ftp nf_conntrack_ipv4 xt_state
> nf_conntrack nfnetlink iptable_filter ip_tables x_tables ppdev radeon
> drm cpufreq_userspace cpufreq_stats cpufreq_powersave cpufreq_ondemand
> freq_table cpufreq_conservative tc1100_wmi pcc_acpi dev_acpi sony_acpi
> video sbs i2c_ec dock button battery container ac asus_acpi backlight
> ipv6 fuse lp snd_cmipci gameport snd_pcm_oss snd_mixer_oss snd_pcm
> snd_page_alloc snd_opl3_lib snd_hwdep snd_mpu401_uart snd_seq_dummy
> snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event i2c_viapro
> parport_pc parport pcspkr psmouse i2c_core snd_seq snd_timer
> snd_seq_device rtc via_ircc snd irda soundcore crc_ccitt serio_raw
> via_agp agpgart shpchp pci_hotplug af_packet evdev tsdev ext3 jbd
> mbcache ide_cd cdrom ide_disk ata_generic libata scsi_mod via82cxxx
> 8139too floppy 8139cp mii generic ohci1394 ieee1394 ehci_hcd uhci_hcd
> usbcore raid10 raid456 xor raid1 raid0 multipath linear md_mod thermal
> processor fan dm_mod fbcon tileblit font bitblit softcursor vesafb
> capability commoncap
> [326735.692550] CPU: 0
> [326735.692552] EIP: 0060:[<c015f581>] Not tainted VLI
> [326735.692553] EFLAGS: 00210082 (2.6.20-16-386 #2)
> [326735.692565] EIP is at kfree+0x41/0x80
> [326735.692568] eax: 40000080 ebx: 0000001b ecx: dfffb3c4 edx: c11ce340
> [326735.692572] esi: ce71ac00 edi: 00200286 ebp: cb2d64a0 esp: d0e4bdd8
> [326735.692575] ds: 007b es: 007b ss: 0068
> [326735.692579] Process firefox-bin (pid: 6763, ti=d0e4a000
> task=cf56c590 task.ti=d0e4a000)
> [326735.692582] Stack: cb2d64a0 d0e4bedc d0e4bea0 c02701f8 00000020
> c02d0c4d c026d39d ffffffff
> [326735.692589] d032bc80 d032bdc0 cb2d64d0 d032bcd4 d0e4bea0
> cf12d8c0 00000020 00000001
> [326735.692596] 00000001 ffffffa1 00000000 d0e4be80 00001302
> 00000000 00000000 00000000
> [326735.692601] Call Trace:
> [326735.692608] [<c02701f8>] kfree_skbmem+0x8/0x80
> [326735.692619] [<c02d0c4d>] unix_stream_recvmsg+0x1ad/0x540
> [326735.692627] [<c026d39d>] sock_alloc_send_skb+0x16d/0x1c0
> [326735.692659] [<c011fad6>] current_fs_time+0x46/0x50
> [326735.692670] [<c026a37f>] sock_aio_read+0x11f/0x130
> [326735.692679] [<c0168f2b>] pipe_write+0x22b/0x470
> [326735.692706] [<c0162ce5>] do_sync_read+0xd5/0x120
> [326735.692729] [<c012ded0>] autoremove_wake_function+0x0/0x50
> [326735.692746] [<c0130a72>] hrtimer_run_queues+0xf2/0x120
> [326735.692754] [<c02cfb79>] unix_ioctl+0x89/0xc0
> [326735.692771] [<c016375c>] vfs_read+0x17c/0x190
> [326735.692782] [<c0163b11>] sys_read+0x41/0x70
> [326735.692793] [<c0102fc0>] sysenter_past_esp+0x69/0xa9
> [326735.692817] =======================
> [326735.692819] Code: 05 00 00 00 00 8d 96 00 00 00 40 89 c7 c1 ea 0c
> c1 e2 05 03 15 80 ba 44 c0 8b 02 f6 c4 40 75 2b 8b 02 84 c0 79 37 8b
> 4a 18 8b 19 <8b> 03 3b 43 04 73 1e 89 74 83 10 83 c0 01 89 03 89 f8 50
> 9d 8d
> [326735.692843] EIP: [<c015f581>] kfree+0x41/0x80 SS:ESP 0068:d0e4bdd8
> [326735.692849]
^ permalink raw reply
* [RFC] IP_RECVERRC
From: jamal @ 2007-08-10 13:35 UTC (permalink / raw)
To: netdev; +Cc: Andi Kleen, David Miller
It seems there are a lot of dumbass apps (latest i have found is iperf
when analyzing batching results) out there whose performance is affected
if they dont set IP_RECVERR.
If you set that option though you end up getting all these skbs back
to the app which i see as unnecessary work if i am uninterested. I would
like to not do a recvmsg to find out what those messages are - rather
just receiving any errors back.
My proposal is to add another option which is mutually exclusive with
IP_RECVERR that allows for errors only.
Can i get a ye before i implement?
Andi, CCing you because i think you may be the person who added
IP_RECVERR (at least the first time i heard it a few years back was from
you).
cheers,
jamal
^ permalink raw reply
* Re: [PATCH RFC]: napi_struct V5
From: jamal @ 2007-08-10 13:55 UTC (permalink / raw)
To: Roland Dreier
Cc: Shirley Ma, David Miller, jgarzik, netdev, rusty, shemminger
In-Reply-To: <adamyx0od9p.fsf@cisco.com>
On Thu, 2007-09-08 at 09:58 -0700, Roland Dreier wrote:
> Could you explain why this is unfair?
The simple answer is the core attempts DRR scheduling (search for the
paper by Varghese et al for more details)
If you have multiple users of a resource (network interfaces in this
case), then the quantum defines their weight. If you use more than your
fair quota, then you are being unfair.
> This is an honest question: I'm
> not trying to be difficult, I just don't see how this implementation
> leads to unfairness. If a driver uses *less* than its full budget in
> the poll routine, requests that the poll routine be rescheduled and
> then returns, it seems to me that the effect on other interfaces would
> be to give them more than their fair share of NAPI processing time.
Yes, thats what the "deficit" part of DRR does; however, you still will
be unfair by utilizing larger quanta.
> Also, perhaps it would be a good idea to explain exactly what the
> ipoib driver is doing in its NAPI poll routine. The difficultly is
> that the IB "interrupt" semantics are not a perfect fit for NAPI -- in
> effect, IB just gives us an edge-triggered one-shot interrupt, and so
> there is an unadvoidable race between detecting that there is no more
> work to do and enabling the interrupt. It's not worth going into the
> details of why things are this way,
Talk to your vendor (your hardware guys in your case ;->) next time to
fix their chip.
The best scheme is to allow a Clear-on-write only on the specific
bit/event.
> but IB can return a hint that says
> "you may have missed an event" when enabling the interrupt, which can
> be used to close the race.
Certainly helps. Is this IB specific or hardware specific?
> So the two implementations being discussed
> are roughly:
>
> if (may_have_missed_event &&
> netif_rx_reschedule(napi))
> goto poll_more;
>
> versus
>
> if (may_have_missed_event) {
> netif_rx_reschedule(napi))
> return done;
> }
>
> The second one seems to perform better because in the missed event
> case, it gives a few more packets a chance to arrive so that we can
> amortize the polling overhead a little more.
Theory makes sense. Have you validated?
> To be honest, I've never
> been able to come up with a good story of why the IBM hardware where
> this makes a measurable difference hits the missed event case enough
> for it to matter.
Someone needs to prove one of the schemes is better. Regardless, either
scheme seems to me to be viable as long as you dont violate your
quantum.
cheers,
jamal
^ permalink raw reply
* Re: [RFC] IP_RECVERRC
From: Andi Kleen @ 2007-08-10 14:02 UTC (permalink / raw)
To: jamal; +Cc: netdev, Andi Kleen, David Miller
In-Reply-To: <1186752912.5188.12.camel@localhost>
On Fri, Aug 10, 2007 at 09:35:12AM -0400, jamal wrote:
>
> It seems there are a lot of dumbass apps (latest i have found is iperf
> when analyzing batching results) out there whose performance is affected
> if they dont set IP_RECVERR.
Affected in what way?
> If you set that option though you end up getting all these skbs back
IP_RECVERR just delivers ICMPs. Do you mean those with "all these skbs" ?
> to the app which i see as unnecessary work if i am uninterested. I would
> like to not do a recvmsg to find out what those messages are - rather
> just receiving any errors back.
> My proposal is to add another option which is mutually exclusive with
> IP_RECVERR that allows for errors only.
What ICMPs do you not want?
-Andi
^ permalink raw reply
* Re: [RFC] IP_RECVERRC
From: jamal @ 2007-08-10 14:30 UTC (permalink / raw)
To: Andi Kleen; +Cc: netdev, David Miller
In-Reply-To: <20070810140214.GA10331@one.firstfloor.org>
On Fri, 2007-10-08 at 16:02 +0200, Andi Kleen wrote:
> On Fri, Aug 10, 2007 at 09:35:12AM -0400, jamal wrote:
>
> Affected in what way?
>
They dont get errors back and they just keep sending even in the
presence of errors - take a look at ip_push_pending_frames. I have been
struggling initially to unconditionally mod that part, but it may break
certain apps expectations.
> > If you set that option though you end up getting all these skbs back
>
> IP_RECVERR just delivers ICMPs. Do you mean those with "all these skbs" ?
yes - sorry thats what i meant; the app has to do a recvmsg to grab them
> > to the app which i see as unnecessary work if i am uninterested. I would
> > like to not do a recvmsg to find out what those messages are - rather
> > just receiving any errors back.
> > My proposal is to add another option which is mutually exclusive with
> > IP_RECVERR that allows for errors only.
>
> What ICMPs do you not want?
All.
cheers,
jamal
^ permalink raw reply
* Re: [PATCH 1/24] make atomic_read() behave consistently on alpha
From: Paul E. McKenney @ 2007-08-10 15:02 UTC (permalink / raw)
To: Andi Kleen
Cc: Herbert Xu, csnook, linux-kernel, linux-arch, torvalds, netdev,
akpm, heiko.carstens, davem, schwidefsky, wensong, horms, wjiang,
cfriesen, zlynx, rpjday, jesper.juhl
In-Reply-To: <200708101108.20897.ak@suse.de>
On Fri, Aug 10, 2007 at 11:08:20AM +0200, Andi Kleen wrote:
> On Friday 10 August 2007 10:21:46 Herbert Xu wrote:
> > Paul E. McKenney <paulmck@linux.vnet.ibm.com> wrote:
> > >
> > > The compiler is within its rights to read a 32-bit quantity 16 bits at
> > > at time, even on a 32-bit machine. I would be glad to help pummel any
> > > compiler writer that pulls such a dirty trick, but the C standard really
> > > does permit this.
> >
> > Code all over the kernel assumes that 32-bit reads/writes
> > are atomic so while such a compiler might be legal it certainly
> > can't compile Linux.
>
> Yes, the kernel requirements are much stricter than ISO-C. And besides
> it is a heavy user of C extensions anyways. On the other hand some of the
> C99 extensions are not allowed. And then there is sparse, which enforces
> a language which sometimes is quite far from standard C. You could say it is
> written in Linux-C, not ISO C.
Understood. My question is "why do we want the semantics of atomic_read()
and atomic_set() to differ?"
Thanx, Paul
^ permalink raw reply
* Re: 2.6.23-rc2-mm2
From: Michal Piotrowski @ 2007-08-10 16:16 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Eric W. Biederman, Netdev, coreteam
In-Reply-To: <20070809224254.11f42716.akpm@linux-foundation.org>
Andrew Morton pisze:
> ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.23-rc2/2.6.23-rc2-mm2/
>
Yet another sysctl table check failed
[ 88.949055] Netfilter messages via NETLINK v0.30.
[ 89.485399] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
[ 89.491892] sysctl table check failed: /net/netfilter/nf_conntrack_generic_timeout .3.19.13 Missing strategy
[ 89.558178] xt_state: Unknown symbol nf_conntrack_untracked
[ 89.563942] xt_state: Unknown symbol nf_ct_l3proto_module_put
[ 89.569870] xt_state: Unknown symbol nf_ct_l3proto_try_module_get
[ 90.852319] NET: Registered protocol family 17
Regards,
Michal
--
LOG
http://www.stardust.webpages.pl/log/
^ permalink raw reply
* Re: [PATCH] [NET] ethtool: Add LRO support
From: Kok, Auke @ 2007-08-10 16:24 UTC (permalink / raw)
To: Jeff Garzik; +Cc: davem, netdev, ossthema
In-Reply-To: <46BC2504.9010400@garzik.org>
Jeff Garzik wrote:
> Auke Kok wrote:
>> Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
>> ---
>>
>> include/linux/ethtool.h | 8 +++++++
>> include/linux/netdevice.h | 1 +
>> net/core/ethtool.c | 53 +++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 62 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index 23ccea8..a97248e 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -272,6 +272,8 @@ u32 ethtool_op_get_tso(struct net_device *dev);
>> int ethtool_op_set_tso(struct net_device *dev, u32 data);
>> u32 ethtool_op_get_ufo(struct net_device *dev);
>> int ethtool_op_set_ufo(struct net_device *dev, u32 data);
>> +u32 ethtool_op_get_lro(struct net_device *dev);
>> +int ethtool_op_set_lro(struct net_device *dev, u32 data);
>
> I'm thinking we don't need to keep adding two function pointers for each
> boolean choice.
>
> I propose adding two operations:
>
> get-flags: return 32-bit (even on 64-bit platforms) flags bitmap
> set-flags: set 32-bit flags bitmap
>
> The 32 bits shall be divided as follows:
>
> bits 0-23: ETHTOOL_FLAG_xxx defined in linux/ethtool.h
> bits 24-31: driver-specific boolean flags
>
> The driver-specific flags are first enumerated by userland via an
> ETHTOOL_GSTRINGS call, using new string set ETH_SS_FLAGS. The first
> string returned names the first driver-private flag (bit 24). This also
> indicates that driver-private bit 24 is a valid flag for this driver and
> network interface.
>
> The overall goal is to replace get-LRO/set-LRO operations with the
> setting/clearing of ETH_FLAG_LRO, and as well, provide a more-scalable
> ethtool interface.
>
> I'll code this up, along with the associated generic helpers
> (net/core/ethtool.c), if there are no objections.
absolutely not. While going over the flags in netdevice.h I can already see that
the room for more flags is rapidly becoming smaller. Unfortunately we're stuck
with the current flags for compatiblity :)
The above idea sounds good to me and should give that room.
Auke
^ permalink raw reply
* Re: [RFC] IP_RECVERRC
From: Andi Kleen @ 2007-08-10 16:26 UTC (permalink / raw)
To: jamal; +Cc: Andi Kleen, netdev, David Miller
In-Reply-To: <1186756212.5163.4.camel@localhost>
On Fri, Aug 10, 2007 at 10:30:12AM -0400, jamal wrote:
> On Fri, 2007-10-08 at 16:02 +0200, Andi Kleen wrote:
> > On Fri, Aug 10, 2007 at 09:35:12AM -0400, jamal wrote:
>
> >
> > Affected in what way?
> >
>
> They dont get errors back and they just keep sending even in the
> presence of errors - take a look at ip_push_pending_frames. I have been
> struggling initially to unconditionally mod that part, but it may break
> certain apps expectations.
Are we talking about TCP or UDP/RAW?
The reason why IP_RECVERR was invented was that for non connected
DGRAM sockets there was no way to figure out for which target host
the error was. So they were dropped. With IP_RECVERR you can get them
together with the original target address.
If you connect the DGRAM socket and don't set IP_RECVERR you will just get
errnos -- that might be what you want.
If you're talking about TCP: IP_RECVERR never made too much sense here.
Normally TCP only reports errors after a major timeout.
At some point Alexey added an extension that if IP_RECVERR is set
you won't need to wait on the timeout, but get the error immediately
delivered using MSG_ERRQUEUE. That actually breaks TCP because it
is not resistent to shifting routes etc. anymore so it's a pretty bad idea.
If for TCP you just want the error delivery without MSG_ERRQUEUE
you could just decrease the max timeouts. Then major timeouts
will happen sooner and you'll get the errnos sooner too.
Of course TCP will be far more unreliable than it is. But it might
be ok for some few applications who really know what they're doing
(but more likely it is just programmer hybris who think
they know all about the networks the app will ever be deployed on)
Anyways, it might make sense to set these timeouts per socket (right now
it is only global sysctl), but on the other hand that would bloat
the already bloated tcp_sock even more.
-Andi
^ permalink raw reply
* Re: 2.6.23-rc2-mm2
From: Gabriel C @ 2007-08-10 16:37 UTC (permalink / raw)
To: Michal Piotrowski
Cc: Andrew Morton, linux-kernel, Eric W. Biederman, Netdev, coreteam
In-Reply-To: <46BC8F71.3070006@googlemail.com>
Michal Piotrowski wrote:
> Andrew Morton pisze:
>> ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.23-rc2/2.6.23-rc2-mm2/
>>
>
> Yet another sysctl table check failed
>
> [ 88.949055] Netfilter messages via NETLINK v0.30.
> [ 89.485399] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
> [ 89.491892] sysctl table check failed: /net/netfilter/nf_conntrack_generic_timeout .3.19.13 Missing strategy
> [ 89.558178] xt_state: Unknown symbol nf_conntrack_untracked
> [ 89.563942] xt_state: Unknown symbol nf_ct_l3proto_module_put
> [ 89.569870] xt_state: Unknown symbol nf_ct_l3proto_try_module_get
> [ 90.852319] NET: Registered protocol family 17
>
And maybe this ?
http://lkml.org/lkml/2007/8/10/112
> Regards,
> Michal
>
Gabriel
^ permalink raw reply
* Re: [Bugme-new] [Bug 8876] New: Not all IPs are shown by "ip addr show"
From: Andrew Morton @ 2007-08-10 16:43 UTC (permalink / raw)
To: netdev; +Cc: gentuu, bugme-daemon@kernel-bugs.osdl.org
In-Reply-To: <bug-8876-10286@http.bugzilla.kernel.org/>
On Fri, 10 Aug 2007 05:58:25 -0700 (PDT) bugme-daemon@bugzilla.kernel.org wrote:
> http://bugzilla.kernel.org/show_bug.cgi?id=8876
>
> Summary: Not all IPs are shown by "ip addr show"
> Product: Networking
> Version: 2.5
> KernelVersion: >=2.6.22 (2.6.23.x too)
> Platform: All
> OS/Version: Linux
> Tree: Mainline
> Status: NEW
> Severity: high
> Priority: P1
> Component: IPV4
> AssignedTo: shemminger@osdl.org
> ReportedBy: gentuu@gmail.com
>
>
> Most recent kernel where this bug did not occur: 2.6.21.x
a regression.
> Distribution: no matter
> Hardware Environment: generic i686
> Software Environment: GNU
> Problem Description:
> Not all ips are shown by "ip addr show" command when IPs number assigned to an
> interface is more than 60-80 (in fact it depends on broadcast/label etc
> presence on each address).
>
> Steps to reproduce:
> It's terribly simple to reproduce:
>
> # for i in $(seq 1 100); do ip ad add 10.0.$i.1/24 dev eth10 ; done
> # ip addr show
>
> this will _not_ show all IPs.
> Looks like the problem is in netlink/ipv4 message processing.
>
^ 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