Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 6/24] make atomic_read() behave consistently on frv
From: Paul E. McKenney @ 2007-08-15 20:15 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Herbert Xu, csnook, dhowells, linux-kernel, linux-arch, torvalds,
	netdev, akpm, ak, heiko.carstens, davem, schwidefsky, wensong,
	horms, wjiang, cfriesen, zlynx, rpjday, jesper.juhl,
	Arnd Bergmann
In-Reply-To: <46C2FFDD.5000600@yahoo.com.au>

On Wed, Aug 15, 2007 at 11:30:05PM +1000, Nick Piggin wrote:
> Paul E. McKenney wrote:
> >On Tue, Aug 14, 2007 at 03:34:25PM +1000, Nick Piggin wrote:
> 
> >>Maybe it is the safe way to go, but it does obscure cases where there
> >>is a real need for barriers.
> >
> >
> >I prefer burying barriers into other primitives.
> 
> When they should naturally be there, eg. locking or the RCU primitives,
> I agree.
> 
> I don't like having them scattered in various "just in case" places,
> because it makes both the users and the APIs hard to understand and
> change.

I certainly agree that we shouldn't do volatile just for the fun of it,
and also that use of volatile should be quite rare.

> Especially since several big architectures don't have volatile in their
> atomic_get and _set, I think it would be a step backwards to add them in
> as a "just in case" thin now (unless there is a better reason).

Good point, except that I would expect gcc's optimization to continue
to improve.  I would like the kernel to be able to take advantage of
improved optimization, which means that we are going to have to make
a few changes.  Adding volatile to atomic_get() and atomic_set() is
IMHO one of those changes.

> >>Many atomic operations are allowed to be reordered between CPUs, so
> >>I don't have a good idea for the rationale to order them within the
> >>CPU (also loads and stores to long and ptr types are not ordered like
> >>this, although we do consider those to be atomic operations too).
> >>
> >>barrier() in a way is like enforcing sequential memory ordering
> >>between process and interrupt context, wheras volatile is just
> >>enforcing coherency of a single memory location (and as such is
> >>cheaper).
> >
> >
> >barrier() is useful, but it has the very painful side-effect of forcing
> >the compiler to dump temporaries.  So we do need something that is
> >not quite so global in effect.
> 
> Yep.
> 
> >>What do you think of this crazy idea?
> >>
> >>/* Enforce a compiler barrier for only operations to location X.
> >>* Call multiple times to provide an ordering between multiple
> >>* memory locations. Other memory operations can be assumed by
> >>* the compiler to remain unchanged and may be reordered
> >>*/
> >>#define order(x) asm volatile("" : "+m" (x))
> >
> >There was something very similar discussed earlier in this thread,
> >with quite a bit of debate as to exactly what the "m" flag should
> >look like.  I suggested something similar named ACCESS_ONCE in the
> >context of RCU (http://lkml.org/lkml/2007/7/11/664):
> 
> Oh, I missed that earlier debate. Will go have a look.
> 
> >	#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
> >
> >The nice thing about this is that it works for both loads and stores.
> >Not clear that order() above does this -- I get compiler errors when
> >I try something like "b = order(a)" or "order(a) = 1" using gcc 4.1.2.
> 
> As Arnd ponted out, order() is not supposed to be an lvalue, but a
> statement like the rest of our memory ordering API.
> 
> As to your followup question of why to use it over ACCESS_ONCE. I
> guess, aside from consistency with the rest of the barrier APIs, you
> can use it in other primitives when you don't actually know what the
> caller is going to do or if it even will make an access. You could
> also use it between calls to _other_ primitives, etc... it just
> seems more flexible to me, but I haven't actually used such a thing
> in real code...
> 
> ACCESS_ONCE doesn't seem as descriptive. What it results in is the
> memory location being loaded or stored (presumably once exactly),
> but I think the more general underlying idea is a barrier point.

OK, first, I am not arguing that ACCESS_ONCE() can replace all current
uses of barrier().  Similarly, rcu_dereference(), rcu_assign_pointer(),
and the various RCU versions of the list-manipulation API in no way
replaced all uses of explicit memory barriers.  However, I do believe that
these API are much easier to use (where they apply, of course) than were
the earlier idioms involving explicit memory barriers.

But we of course need to keep the explicit memory and compiler barriers
for other situations.

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH 6/24] make atomic_read() behave consistently on frv
From: Segher Boessenkool @ 2007-08-15 20:13 UTC (permalink / raw)
  To: paulmck
  Cc: heiko.carstens, horms, linux-kernel, rpjday, ak, netdev, cfriesen,
	akpm, torvalds, Nick Piggin, linux-arch, jesper.juhl, zlynx,
	schwidefsky, Chris Snook, davem, wensong, wjiang, David Howells
In-Reply-To: <20070815195915.GL9645@linux.vnet.ibm.com>

>>>>> Well if there is only one memory location involved, then smp_rmb()
>>>>> isn't
>>>>> going to really do anything anyway, so it would be incorrect to use
>>>>> it.
>>>>
>>>> rmb() orders *any* two reads; that includes two reads from the same
>>>> location.
>>>
>>> If the two reads are to the same location, all CPUs I am aware of
>>> will maintain the ordering without need for a memory barrier.
>>
>> That's true of course, although there is no real guarantee for that.
>
> A CPU that did not provide this property ("cache coherence") would be
> most emphatically reviled.

That doesn't have anything to do with coherency as far as I can see.

It's just about the order in which a CPU (speculatively) performs the 
loads
(which isn't necessarily the same as the order in which it executes the
corresponding instructions, even).

> So we are pretty safe assuming that CPUs
> will provide it.

Yeah, pretty safe.  I just don't like undocumented assumptions :-)


Segher


^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Paul E. McKenney @ 2007-08-15 20:17 UTC (permalink / raw)
  To: Satyam Sharma
  Cc: Segher Boessenkool, horms, Stefan Richter,
	Linux Kernel Mailing List, rpjday, netdev, ak, cfriesen,
	Heiko Carstens, jesper.juhl, linux-arch, Andrew Morton, zlynx,
	clameter, schwidefsky, Chris Snook, Herbert Xu, davem,
	Linus Torvalds, wensong, wjiang
In-Reply-To: <alpine.LFD.0.999.0708160118330.16414@enigma.security.iitk.ac.in>

On Thu, Aug 16, 2007 at 01:24:42AM +0530, Satyam Sharma wrote:
> [ The Cc: list scares me. Should probably trim it. ]

Trim away!  ;-)

> On Wed, 15 Aug 2007, Paul E. McKenney wrote:
> 
> > On Wed, Aug 15, 2007 at 08:31:25PM +0200, Segher Boessenkool wrote:
> > > >>How does the compiler know that msleep() has got barrier()s?
> > > >
> > > >Because msleep_interruptible() is in a separate compilation unit,
> > > >the compiler has to assume that it might modify any arbitrary global.
> > > 
> > > No; compilation units have nothing to do with it, GCC can optimise
> > > across compilation unit boundaries just fine, if you tell it to
> > > compile more than one compilation unit at once.
> > 
> > Last I checked, the Linux kernel build system did compile each .c file
> > as a separate compilation unit.
> > 
> > > What you probably mean is that the compiler has to assume any code
> > > it cannot currently see can do anything (insofar as allowed by the
> > > relevant standards etc.)
> 
> I think this was just terminology confusion here again. Isn't "any code
> that it cannot currently see" the same as "another compilation unit",
> and wouldn't the "compilation unit" itself expand if we ask gcc to
> compile more than one unit at once? Or is there some more specific
> "definition" for "compilation unit" (in gcc lingo, possibly?)

This is indeed my understanding -- "compilation unit" is whatever the
compiler looks at in one go.  I have heard the word "module" used for
the minimal compilation unit covering a single .c file and everything
that it #includes, but there might be a better name for this.

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 18:31 UTC (permalink / raw)
  To: paulmck
  Cc: horms, Stefan Richter, Satyam Sharma, Linux Kernel Mailing List,
	rpjday, netdev, ak, cfriesen, Heiko Carstens, jesper.juhl,
	linux-arch, Andrew Morton, zlynx, clameter, schwidefsky,
	Chris Snook, Herbert Xu, davem, Linus Torvalds, wensong, wjiang
In-Reply-To: <20070815162722.GD9645@linux.vnet.ibm.com>

>> How does the compiler know that msleep() has got barrier()s?
>
> Because msleep_interruptible() is in a separate compilation unit,
> the compiler has to assume that it might modify any arbitrary global.

No; compilation units have nothing to do with it, GCC can optimise
across compilation unit boundaries just fine, if you tell it to
compile more than one compilation unit at once.

What you probably mean is that the compiler has to assume any code
it cannot currently see can do anything (insofar as allowed by the
relevant standards etc.)

> In many cases, the compiler also has to assume that 
> msleep_interruptible()
> might call back into a function in the current compilation unit, thus
> possibly modifying global static variables.

It most often is smart enough to see what compilation-unit-local
variables might be modified that way, though :-)


Segher


^ permalink raw reply

* Re: [PATCH 6/24] make atomic_read() behave consistently on frv
From: Paul E. McKenney @ 2007-08-15 20:38 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: heiko.carstens, horms, linux-kernel, rpjday, ak, netdev, cfriesen,
	akpm, torvalds, Nick Piggin, linux-arch, jesper.juhl, zlynx,
	schwidefsky, Chris Snook, davem, wensong, wjiang, David Howells
In-Reply-To: <d2cd1065faf8a13040e8a2405c363aa1@kernel.crashing.org>

On Wed, Aug 15, 2007 at 10:13:49PM +0200, Segher Boessenkool wrote:
> >>>>>Well if there is only one memory location involved, then smp_rmb()
> >>>>>isn't
> >>>>>going to really do anything anyway, so it would be incorrect to use
> >>>>>it.
> >>>>
> >>>>rmb() orders *any* two reads; that includes two reads from the same
> >>>>location.
> >>>
> >>>If the two reads are to the same location, all CPUs I am aware of
> >>>will maintain the ordering without need for a memory barrier.
> >>
> >>That's true of course, although there is no real guarantee for that.
> >
> >A CPU that did not provide this property ("cache coherence") would be
> >most emphatically reviled.
> 
> That doesn't have anything to do with coherency as far as I can see.
> 
> It's just about the order in which a CPU (speculatively) performs the 
> loads
> (which isn't necessarily the same as the order in which it executes the
> corresponding instructions, even).

Please check the definition of "cache coherence".

Summary: the CPU is indeed within its rights to execute loads and stores
to a single variable out of order, -but- only if it gets the same result
that it would have obtained by executing them in order.  Which means that
any reordering of accesses by a single CPU to a single variable will be
invisible to the software.

> >So we are pretty safe assuming that CPUs
> >will provide it.
> 
> Yeah, pretty safe.  I just don't like undocumented assumptions :-)

Can't help you there!  ;-)

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 20:47 UTC (permalink / raw)
  To: Satyam Sharma
  Cc: horms, Stefan Richter, Linux Kernel Mailing List,
	Paul E. McKenney, ak, netdev, cfriesen, Heiko Carstens, rpjday,
	jesper.juhl, linux-arch, Andrew Morton, zlynx, clameter,
	schwidefsky, Chris Snook, Herbert Xu, davem, Linus Torvalds,
	wensong, wjiang
In-Reply-To: <alpine.LFD.0.999.0708160118330.16414@enigma.security.iitk.ac.in>

>>> What you probably mean is that the compiler has to assume any code
>>> it cannot currently see can do anything (insofar as allowed by the
>>> relevant standards etc.)
>
> I think this was just terminology confusion here again. Isn't "any code
> that it cannot currently see" the same as "another compilation unit",

It is not; try  gcc -combine  or the upcoming link-time optimisation
stuff, for example.

> and wouldn't the "compilation unit" itself expand if we ask gcc to
> compile more than one unit at once? Or is there some more specific
> "definition" for "compilation unit" (in gcc lingo, possibly?)

"compilation unit" is a C standard term.  It typically boils down
to "single .c file".


Segher


^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 20:42 UTC (permalink / raw)
  To: Satyam Sharma
  Cc: Christoph Lameter, heiko.carstens, horms, Stefan Richter,
	Linux Kernel Mailing List, Paul E. McKenney, netdev, ak, cfriesen,
	rpjday, jesper.juhl, linux-arch, Andrew Morton, zlynx,
	schwidefsky, Chris Snook, Herbert Xu, davem, Linus Torvalds,
	wensong, wjiang
In-Reply-To: <alpine.LFD.0.999.0708160102550.16414@enigma.security.iitk.ac.in>

>> What volatile does are a) never optimise away a read (or write)
>> to the object, since the data can change in ways the compiler
>> cannot see; and b) never move stores to the object across a
>> sequence point.  This does not mean other accesses cannot be
>> reordered wrt the volatile access.
>>
>> If the abstract machine would do an access to a volatile-
>> qualified object, the generated machine code will do that
>> access too.  But, for example, it can still be optimised
>> away by the compiler, if it can prove it is allowed to.
>
> As (now) indicated above, I had meant multiple volatile accesses to
> the same object, obviously.

Yes, accesses to volatile objects are never reordered with
respect to each other.

> BTW:
>
> #define atomic_read(a)	(*(volatile int *)&(a))
> #define atomic_set(a,i)	(*(volatile int *)&(a) = (i))
>
> int a;
>
> void func(void)
> {
> 	int b;
>
> 	b = atomic_read(a);
> 	atomic_set(a, 20);
> 	b = atomic_read(a);
> }
>
> gives:
>
> func:
> 	pushl	%ebp
> 	movl	a, %eax
> 	movl	%esp, %ebp
> 	movl	$20, a
> 	movl	a, %eax
> 	popl	%ebp
> 	ret
>
> so the first atomic_read() wasn't optimized away.

Of course.  It is executed by the abstract machine, so
it will be executed by the actual machine.  On the other
hand, try

	b = 0;
	if (b)
		b = atomic_read(a);

or similar.


Segher


^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 20:52 UTC (permalink / raw)
  To: paulmck
  Cc: horms, Stefan Richter, Satyam Sharma, Linux Kernel Mailing List,
	rpjday, netdev, ak, cfriesen, Heiko Carstens, jesper.juhl,
	linux-arch, Andrew Morton, zlynx, clameter, schwidefsky,
	Chris Snook, Herbert Xu, davem, Linus Torvalds, wensong, wjiang
In-Reply-To: <20070815201748.GN9645@linux.vnet.ibm.com>

>> I think this was just terminology confusion here again. Isn't "any 
>> code
>> that it cannot currently see" the same as "another compilation unit",
>> and wouldn't the "compilation unit" itself expand if we ask gcc to
>> compile more than one unit at once? Or is there some more specific
>> "definition" for "compilation unit" (in gcc lingo, possibly?)
>
> This is indeed my understanding -- "compilation unit" is whatever the
> compiler looks at in one go.  I have heard the word "module" used for
> the minimal compilation unit covering a single .c file and everything
> that it #includes, but there might be a better name for this.

Yes, that's what's called "compilation unit" :-)

[/me double checks]

Erm, the C standard actually calls it "translation unit".

To be exact, to avoid any more confusion:

5.1.1.1/1:
A C program need not all be translated at the same time. The
text of the program is kept in units called source files, (or
preprocessing files) in this International Standard. A source
file together with all the headers and source files included
via the preprocessing directive #include is known as a
preprocessing translation unit. After preprocessing, a
preprocessing translation unit is called a translation unit.



Segher


^ permalink raw reply

* Re: [patch 08/18] 3c59x: check return of pci_enable_device()
From: Steffen Klassert @ 2007-08-15 20:59 UTC (permalink / raw)
  To: Mark Hindley; +Cc: Jeff Garzik, akpm, netdev
In-Reply-To: <20070815163000.GB619@bayes.mathematik.tu-chemnitz.de>

On Wed, Aug 15, 2007 at 06:30:00PM +0200, Steffen Klassert wrote:
> On Tue, Aug 14, 2007 at 10:54:32AM +0100, Mark Hindley wrote:
> > On Tue, Aug 14, 2007 at 01:33:26AM -0400, Jeff Garzik wrote:
> > > I would strongly prefer that vortex_up return a value, since all the 
> > > important callers of this function can themselves return an error back 
> > > to the system.
> > > 
> > > we can definitely return a meaningful return value here, if 
> > > pci_enable_device() fails, and I would rather not apply a patch that 
> > > fails to propagate a serious condition (pci_enable_device failure is 
> > > indeed serious) when it is possible to do so
> > > 
> > 
> > OK. Any comments on this revised version? I have only ignored the return of
> > vortex_up in vortex_error. It is not immediately clear what to do if
> > vortex_up still fails there after a pci reset.
> > 
> > Mark
> > 
> > 
> > diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
> > index 001c66d..a1dfd6b 100644
> > --- a/drivers/net/3c59x.c
> > +++ b/drivers/net/3c59x.c
> > @@ -705,7 +705,7 @@ static struct {
> >  
> >  static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
> >  				   int chip_idx, int card_idx);
> > -static void vortex_up(struct net_device *dev);
> > +static int vortex_up(struct net_device *dev);
> >  static void vortex_down(struct net_device *dev, int final);
> >  static int vortex_open(struct net_device *dev);
> >  static void mdio_sync(void __iomem *ioaddr, int bits);
> > @@ -841,8 +841,11 @@ static int vortex_resume(struct pci_dev *pdev)
> >  			return -EBUSY;
> >  		}
> >  		if (netif_running(dev)) {
> > -			vortex_up(dev);
> > -			netif_device_attach(dev);
> > +			err = vortex_up(dev);
> > +			if (err)
> > +				return err;
> > +			else  
> > +				netif_device_attach(dev);
> >  		}
> >  	}
> >  	return 0;
> 
> I think we should free the requested irq if vortex_up really fails here.
> 

I was wrong, this will be done in vortex_close. So it is OK as it is.

Steffen 

^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 20:58 UTC (permalink / raw)
  To: Satyam Sharma
  Cc: Christoph Lameter, heiko.carstens, horms, Stefan Richter,
	Linux Kernel Mailing List, Paul E. McKenney, netdev, ak, cfriesen,
	rpjday, jesper.juhl, linux-arch, Andrew Morton, zlynx,
	schwidefsky, Chris Snook, Herbert Xu, davem, Linus Torvalds,
	wensong, wjiang
In-Reply-To: <alpine.LFD.0.999.0708152048270.16414@enigma.security.iitk.ac.in>

>>> Of course, if we find there are more callers in the kernel who want 
>>> the
>>> volatility behaviour than those who don't care, we can re-define the
>>> existing ops to such variants, and re-name the existing definitions 
>>> to
>>> somethine else, say "atomic_read_nonvolatile" for all I care.
>>
>> Do we really need another set of APIs?
>
> Well, if there's one set of users who do care about volatile behaviour,
> and another set that doesn't, it only sounds correct to provide both
> those APIs, instead of forcing one behaviour on all users.

But since there currently is only one such API, and there are
users expecting the stronger behaviour, the only sane thing to
do is let the API provide that behaviour.  You can always add
a new API with weaker behaviour later, and move users that are
okay with it over to that new API.


Segher


^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 21:05 UTC (permalink / raw)
  To: paulmck
  Cc: horms, Stefan Richter, Satyam Sharma, Linux Kernel Mailing List,
	rpjday, netdev, ak, cfriesen, Heiko Carstens, jesper.juhl,
	linux-arch, Andrew Morton, zlynx, clameter, schwidefsky,
	Chris Snook, Herbert Xu, davem, Linus Torvalds, wensong, wjiang
In-Reply-To: <20070815185724.GH9645@linux.vnet.ibm.com>

>> No; compilation units have nothing to do with it, GCC can optimise
>> across compilation unit boundaries just fine, if you tell it to
>> compile more than one compilation unit at once.
>
> Last I checked, the Linux kernel build system did compile each .c file
> as a separate compilation unit.

I have some patches to use -combine -fwhole-program for Linux.
Highly experimental, you need a patched bleeding edge toolchain.
If there's interest I'll clean it up and put it online.

David Woodhouse had some similar patches about a year ago.

>>> In many cases, the compiler also has to assume that
>>> msleep_interruptible()
>>> might call back into a function in the current compilation unit, thus
>>> possibly modifying global static variables.
>>
>> It most often is smart enough to see what compilation-unit-local
>> variables might be modified that way, though :-)
>
> Yep.  For example, if it knows the current value of a given such local
> variable, and if all code paths that would change some other variable
> cannot be reached given that current value of the first variable.

Or the most common thing: if neither the address of the translation-
unit local variable nor the address of any function writing to that
variable can "escape" from that translation unit, nothing outside
the translation unit can write to the variable.

> At least given that gcc doesn't know about multiple threads of 
> execution!

Heh, only about the threads it creates itself (not relevant to
the kernel, for sure :-) )


Segher


^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Segher Boessenkool @ 2007-08-15 21:07 UTC (permalink / raw)
  To: paulmck
  Cc: Christoph Lameter, heiko.carstens, horms, Stefan Richter,
	Satyam Sharma, Linux Kernel Mailing List, rpjday, netdev, ak,
	cfriesen, jesper.juhl, linux-arch, Andrew Morton, zlynx,
	schwidefsky, Chris Snook, Herbert Xu, davem, Linus Torvalds,
	wensong, wjiang
In-Reply-To: <20070815190722.GI9645@linux.vnet.ibm.com>

>> Possibly these were too trivial to expose any potential problems that 
>> you
>> may have been referring to, so would be helpful if you could write a 
>> more
>> concrete example / sample code.
>
> The trick is to have a sufficiently complicated expression to force
> the compiler to run out of registers.

You can use -ffixed-XXX to keep the testcase simple.


Segher


^ permalink raw reply

* Re: [PATCH 6/24] make atomic_read() behave consistently on frv
From: Segher Boessenkool @ 2007-08-15 21:15 UTC (permalink / raw)
  To: paulmck
  Cc: heiko.carstens, horms, linux-kernel, rpjday, ak, netdev, cfriesen,
	akpm, torvalds, Nick Piggin, linux-arch, jesper.juhl, zlynx,
	schwidefsky, Chris Snook, davem, wensong, wjiang, David Howells
In-Reply-To: <20070815203836.GO9645@linux.vnet.ibm.com>

> Please check the definition of "cache coherence".

Which of the twelve thousand such definitions?  :-)

> Summary: the CPU is indeed within its rights to execute loads and 
> stores
> to a single variable out of order, -but- only if it gets the same 
> result
> that it would have obtained by executing them in order.  Which means 
> that
> any reordering of accesses by a single CPU to a single variable will be
> invisible to the software.

I'm still not sure if that applies to all architectures.
Doesn't matter anyway, let's kill this thread :-)


Segher


^ permalink raw reply

* skge and sky2 stop working after a few minutes.
From: Sébastien Judenherc @ 2007-08-15 21:20 UTC (permalink / raw)
  To: netdev

Hello,
I can see some very strange problem with sky2 and skge interfaces with 2.6.22,
and also 2.6.23-rc2/3.
After 8-9 minutes, the interfaces stop working. ethtool reports that the link is
down and the only way to make the interfaces usable again is
removing/reinserting the module or running ethtool -r.
This occurs for both sky2 and skge for two PCs connected to a gigabit switch.
The other PCs on the same switch continue to work fine (most are 100Mbit/s). It
also occurs on a third PC with skge, directly connected to a 100Mbit/s interface
over a cross over cable. I didn't notice the problem with 2.6.19.

After 8-9 minutes, the interface stops working. ethtool reports that the link is
down and the only way to make the interface usable again is removing/reinserting
the module or running ethtool -r.

For the skge interface connected to the gigabit switch, here is what ethtool
reports:

Settings for eth0:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Half 1000baseT/Full 
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Half 1000baseT/Full 
        Advertised auto-negotiation: Yes
        Speed: Unknown! (65535)
        Duplex: Unknown! (255)
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: pg
        Wake-on: g
        Current message level: 0x00000037 (55)
        Link detected: no
NIC statistics:
     tx_bytes: 0
     rx_bytes: 0
     tx_broadcast: 0
     rx_broadcast: 0
     tx_multicast: 0
     rx_multicast: 0
     tx_unicast: 0
     rx_unicast: 0
     tx_mac_pause: 0
     rx_mac_pause: 0
     collisions: 0
     multi_collisions: 0
     aborted: 0
     late_collision: 0
     fifo_underrun: 0
     fifo_overflow: 0
     rx_toolong: 0
     rx_jabber: 0
     rx_runt: 0
     rx_too_long: 0
     rx_fcs_error: 0

and here is what dmesg says just after the hangs with debug=16 for skge:
...
eth0: tx queued, slot 127, len 1098
skge eth0: tx done slot 127
skge eth0: rx slot 394 status 0x420100 len 66
skge eth0: rx slot 395 status 0x420100 len 66
eth0: tx queued, slot 0, len 42
skge eth0: tx done slot 0
eth0: tx queued, slot 1, len 74
skge eth0: tx done slot 1
skge eth0: rx slot 396 status 0x420100 len 66
eth0: tx queued, slot 2, len 1414
skge eth0: tx done slot 2
skge eth0: rx slot 397 status 0x420100 len 66
eth0: tx queued, slot 3, len 270
skge eth0: tx done slot 3
skge eth0: rx slot 398 status 0x420100 len 66
eth0: tx queued, slot 4, len 74
skge eth0: tx done slot 4
skge eth0: rx slot 399 status 0x420100 len 66
skge eth0: phy interrupt status 0x400 0x814c
skge eth0: Link is down.

I would be happy to help.

regards
sébastien.


^ permalink raw reply

* Re: linux kernel 2.6.18-20 bug: rcu_read_unlock in __sock_create
From: David Miller @ 2007-08-15 21:46 UTC (permalink / raw)
  To: herbert; +Cc: 123.oleg, netdev, linux-kernel
In-Reply-To: <E1ILEJr-0005Fl-00@gondolin.me.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 15 Aug 2007 16:33:35 +0800

> [NET]: Fix unbalanced rcu_read_unlock in __sock_create
> 
> The recent RCU work created an unbalanced rcu_read_unlock
> in __sock_create.  This patch fixes that.  Reported by
> oleg 123.
> 
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Patch applied, thanks Herbert.

^ permalink raw reply

* [PATCH] [IPv6]: Invalid semicolon after if statement
From: Ilpo Järvinen @ 2007-08-15 21:57 UTC (permalink / raw)
  To: David Miller, YOSHIFUJI Hideaki; +Cc: Netdev

[-- Attachment #1: Type: TEXT/PLAIN, Size: 852 bytes --]


A similar fix to netfilter from Eric Dumazet inspired me to
look around a bit by using some grep/sed stuff as looking for
this kind of bugs seemed easy to automate. This is one of them
I found where it looks like this semicolon is not valid.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
---
 net/ipv6/ipv6_sockglue.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index d684639..761a910 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -820,7 +820,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
 		return 0;
 
 	len = min_t(unsigned int, len, ipv6_optlen(hdr));
-	if (copy_to_user(optval, hdr, len));
+	if (copy_to_user(optval, hdr, len))
 		return -EFAULT;
 	return ipv6_optlen(hdr);
 }
-- 
1.5.0.6

^ permalink raw reply related

* Re: [PATCH] [IPv6]: Invalid semicolon after if statement
From: David Miller @ 2007-08-15 22:08 UTC (permalink / raw)
  To: ilpo.jarvinen; +Cc: yoshfuji, netdev
In-Reply-To: <Pine.LNX.4.64.0708151509520.15670@kivilampi-30.cs.helsinki.fi>

From: "Ilpo_Järvinen" <ilpo.jarvinen@helsinki.fi>
Date: Thu, 16 Aug 2007 00:57:00 +0300 (EEST)

> A similar fix to netfilter from Eric Dumazet inspired me to
> look around a bit by using some grep/sed stuff as looking for
> this kind of bugs seemed easy to automate. This is one of them
> I found where it looks like this semicolon is not valid.
> 
> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>

Yikes!  Makes you want to audit the entire tree for these
things :-)))

Patch applied, thanks a lot Ilpo!

^ permalink raw reply

* [PATCH 2.6.24 1/5]S2io: Enable all the error and alarm indications
From: Ramkrishna Vepa @ 2007-08-16  0:12 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Added support to unmask entire set of device errors and alarms.

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Santosh Rastapur <santosh.rastapur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -Nurp orig/drivers/net/s2io.c patch1/drivers/net/s2io.c
--- orig/drivers/net/s2io.c	2007-08-15 08:04:06.000000000 -0700
+++ patch1/drivers/net/s2io.c	2007-08-15 08:55:53.000000000 -0700
@@ -892,8 +892,9 @@ static void free_shared_mem(struct s2io_
 					k++;
 				}
 				kfree(mac_control->rings[i].ba[j]);
-				nic->mac_control.stats_info->sw_stat.mem_freed 				+= (sizeof(struct buffAdd) * 
-				(rxd_count[nic->rxd_mode] + 1));
+				nic->mac_control.stats_info->sw_stat.mem_freed += 
+					(sizeof(struct buffAdd) * 
+					(rxd_count[nic->rxd_mode] + 1));
 			}
 			kfree(mac_control->rings[i].ba);
 			nic->mac_control.stats_info->sw_stat.mem_freed += 
@@ -1732,6 +1733,365 @@ static int s2io_link_fault_indication(st
 		return MAC_RMAC_ERR_TIMER;
 }
 
+void en_dis_err_alarms(struct s2io_nic *nic, u16 mask, int flag)
+{
+	struct XENA_dev_config __iomem *bar0 = nic->bar0;
+	register u64 val64 = 0, temp64 = 0, gen_int_mask = 0;
+
+	if (mask & TX_DMA_INTR) {
+		gen_int_mask |= TXDMA_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+
+			val64 = TXDMA_TDA_INT|TXDMA_PFC_INT|TXDMA_PCC_INT
+				|TXDMA_TTI_INT|TXDMA_LSO_INT|TXDMA_TPA_INT
+				|TXDMA_SM_INT;
+			temp64 = readq(&bar0->txdma_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->txdma_int_mask);
+
+			val64 = PFC_ECC_DB_ERR|PFC_SM_ERR_ALARM|PFC_MISC_0_ERR
+				|PFC_MISC_1_ERR|PFC_PCIX_ERR|PFC_ECC_SG_ERR;
+			temp64 = readq(&bar0->pfc_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->pfc_err_mask);
+
+			val64 = TDA_Fn_ECC_DB_ERR|TDA_SM0_ERR_ALARM
+				|TDA_SM1_ERR_ALARM|TDA_Fn_ECC_SG_ERR|
+				TDA_PCIX_ERR;
+			temp64 = readq(&bar0->tda_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->tda_err_mask);
+
+			val64 = PCC_FB_ECC_DB_ERR|PCC_TXB_ECC_DB_ERR
+				|PCC_SM_ERR_ALARM|PCC_WR_ERR_ALARM|PCC_N_SERR
+				|PCC_6_COF_OV_ERR|PCC_7_COF_OV_ERR
+				|PCC_6_LSO_OV_ERR|PCC_7_LSO_OV_ERR
+				|PCC_FB_ECC_SG_ERR|PCC_TXB_ECC_SG_ERR;
+			temp64 = readq(&bar0->pcc_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->pcc_err_mask);
+
+			val64 = TTI_SM_ERR_ALARM|TTI_ECC_SG_ERR|TTI_ECC_DB_ERR;
+			temp64 = readq(&bar0->tti_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->tti_err_mask);
+
+
+			val64 = LSO6_ABORT|LSO7_ABORT|LSO6_SM_ERR_ALARM
+				|LSO7_SM_ERR_ALARM|LSO6_SEND_OFLOW
+				|LSO7_SEND_OFLOW;
+			temp64 = readq(&bar0->lso_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->lso_err_mask);
+
+			val64 = TPA_SM_ERR_ALARM|TPA_TX_FRM_DROP;
+			temp64 = readq(&bar0->tpa_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->tpa_err_mask);
+
+			val64 = SM_SM_ERR_ALARM;
+			temp64 = readq(&bar0->sm_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->sm_err_mask);
+		}
+		else {
+			val64 = TXDMA_TDA_INT|TXDMA_PFC_INT|TXDMA_PCC_INT
+				|TXDMA_TTI_INT|TXDMA_LSO_INT|TXDMA_TPA_INT
+				|TXDMA_SM_INT;
+			temp64 = readq(&bar0->txdma_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->txdma_int_mask);
+
+			val64 = PFC_ECC_DB_ERR|PFC_SM_ERR_ALARM|PFC_MISC_0_ERR
+				|PFC_MISC_1_ERR|PFC_PCIX_ERR|PFC_ECC_SG_ERR;
+			temp64 = readq(&bar0->pfc_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->pfc_err_mask);
+
+			val64 = TDA_Fn_ECC_DB_ERR|TDA_SM0_ERR_ALARM
+				|TDA_Fn_ECC_SG_ERR|TDA_SM1_ERR_ALARM
+				|TDA_PCIX_ERR;
+			temp64 = readq(&bar0->tda_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->tda_err_mask);
+
+			val64 = PCC_FB_ECC_DB_ERR|PCC_TXB_ECC_DB_ERR
+				|PCC_SM_ERR_ALARM |PCC_WR_ERR_ALARM|PCC_N_SERR
+				|PCC_FB_ECC_SG_ERR|PCC_TXB_ECC_SG_ERR
+				|PCC_6_COF_OV_ERR|PCC_7_COF_OV_ERR
+				|PCC_6_LSO_OV_ERR|PCC_7_LSO_OV_ERR;
+			temp64 = readq(&bar0->pcc_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->pcc_err_mask);
+
+			val64 = TTI_SM_ERR_ALARM|TTI_ECC_SG_ERR|TTI_ECC_DB_ERR;
+			temp64 = readq(&bar0->tti_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->tti_err_mask);
+
+			val64 = LSO6_ABORT|LSO7_ABORT|LSO6_SM_ERR_ALARM
+				|LSO7_SM_ERR_ALARM|LSO6_SEND_OFLOW
+				|LSO7_SEND_OFLOW;
+			temp64 = readq(&bar0->lso_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->lso_err_mask);
+
+			val64 = TPA_SM_ERR_ALARM|TPA_TX_FRM_DROP;
+			temp64 = readq(&bar0->tpa_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->tpa_err_mask);
+
+			val64 = SM_SM_ERR_ALARM;
+			temp64 = readq(&bar0->sm_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->sm_err_mask);
+		}
+	}
+
+	if (mask & TX_MAC_INTR) {
+		gen_int_mask |= TXMAC_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+			val64 = MAC_INT_STATUS_TMAC_INT;
+			temp64 = readq(&bar0->mac_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->mac_int_mask);
+
+			val64 = TMAC_TX_BUF_OVRN|TMAC_TX_SM_ERR|TMAC_ECC_SG_ERR|
+				TMAC_ECC_DB_ERR|TMAC_DESC_ECC_SG_ERR
+				|TMAC_DESC_ECC_DB_ERR;
+			temp64 = readq(&bar0->mac_tmac_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->mac_tmac_err_mask);
+		}
+		else {
+			val64 = MAC_INT_STATUS_TMAC_INT;
+			temp64 = readq(&bar0->mac_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mac_int_mask);
+
+			val64 = TMAC_ECC_SG_ERR|TMAC_ECC_DB_ERR
+				|TMAC_TX_BUF_OVRN|TMAC_TX_SM_ERR
+				|TMAC_DESC_ECC_SG_ERR|TMAC_DESC_ECC_DB_ERR;
+			temp64 = readq(&bar0->mac_tmac_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mac_tmac_err_mask);
+		}
+	}
+
+	if (mask & TX_XGXS_INTR) {
+		gen_int_mask |= TXXGXS_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+			val64 = XGXS_INT_STATUS_TXGXS;
+			temp64 = readq(&bar0->xgxs_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->xgxs_int_mask);
+
+			val64 = TXGXS_ESTORE_UFLOW|TXGXS_TX_SM_ERR|
+				TXGXS_ECC_SG_ERR|TXGXS_ECC_DB_ERR;
+			temp64 = readq(&bar0->xgxs_txgxs_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->xgxs_txgxs_err_mask);
+		}
+		else {
+			val64 = XGXS_INT_STATUS_TXGXS;
+			temp64 = readq(&bar0->mac_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mac_int_mask);
+
+			val64 = TXGXS_ECC_SG_ERR|TXGXS_ECC_DB_ERR
+				|TXGXS_ESTORE_UFLOW|TXGXS_TX_SM_ERR;
+			temp64 = readq(&bar0->xgxs_txgxs_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->xgxs_txgxs_err_mask);
+		}
+	}
+
+	if (mask & RX_DMA_INTR) {
+		gen_int_mask |= RXDMA_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+			val64 = RXDMA_INT_RC_INT_M|RXDMA_INT_RPA_INT_M
+				|RXDMA_INT_RDA_INT_M|RXDMA_INT_RTI_INT_M;
+			temp64 = readq(&bar0->rxdma_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->rxdma_int_mask);
+
+			val64 = RC_PRCn_ECC_DB_ERR|RC_FTC_ECC_DB_ERR|
+				RC_PRCn_SM_ERR_ALARM|RC_FTC_SM_ERR_ALARM|
+				RC_PRCn_ECC_SG_ERR|RC_FTC_ECC_SG_ERR|
+				RC_RDA_FAIL_WR_Rn;
+			temp64 = readq(&bar0->rc_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->rc_err_mask);
+
+			val64 = PRC_PCI_AB_RD_Rn|PRC_PCI_AB_WR_Rn|
+				PRC_PCI_AB_F_WR_Rn|PRC_PCI_DP_RD_Rn
+				|PRC_PCI_DP_WR_Rn|
+				PRC_PCI_DP_F_WR_Rn;
+			temp64 = readq(&bar0->prc_pcix_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->prc_pcix_err_mask);
+
+			val64 = RPA_SM_ERR_ALARM|RPA_CREDIT_ERR|
+				RPA_ECC_SG_ERR|RPA_ECC_DB_ERR;
+			temp64 = readq(&bar0->rpa_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->rpa_err_mask);
+
+			val64 = RDA_RXDn_ECC_DB_ERR|RDA_FRM_ECC_DB_N_AERR|
+				RDA_SM1_ERR_ALARM|RDA_SM0_ERR_ALARM|
+				RDA_RXD_ECC_DB_SERR|RDA_RXDn_ECC_SG_ERR
+				|RDA_FRM_ECC_SG_ERR|
+				RDA_MISC_ERR|RDA_PCIX_ERR;
+			temp64 = readq(&bar0->rda_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->rda_err_mask);
+
+			val64 = RTI_SM_ERR_ALARM|RTI_ECC_SG_ERR|RTI_ECC_DB_ERR;
+			temp64 = readq(&bar0->rti_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->rti_err_mask);
+		}
+		else {
+			val64 = RXDMA_INT_RC_INT_M|RXDMA_INT_RPA_INT_M
+				|RXDMA_INT_RDA_INT_M|RXDMA_INT_RTI_INT_M;
+			temp64 = readq(&bar0->rxdma_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->rxdma_int_mask);
+
+			val64 = RC_PRCn_ECC_SG_ERR|RC_PRCn_ECC_DB_ERR
+				|RC_FTC_ECC_SG_ERR|RC_FTC_ECC_DB_ERR
+				|RC_PRCn_SM_ERR_ALARM|RC_FTC_SM_ERR_ALARM
+				|RC_RDA_FAIL_WR_Rn;
+			temp64 = readq(&bar0->rc_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->rc_err_mask);
+
+			val64 = PRC_PCI_AB_RD_Rn|PRC_PCI_DP_RD_Rn
+				|PRC_PCI_AB_WR_Rn|PRC_PCI_DP_WR_Rn
+				|PRC_PCI_AB_F_WR_Rn|PRC_PCI_DP_F_WR_Rn;
+			temp64 = readq(&bar0->prc_pcix_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->prc_pcix_err_mask);
+
+			val64 = RPA_ECC_SG_ERR|RPA_ECC_DB_ERR
+				|RPA_FLUSH_REQUEST|RPA_SM_ERR_ALARM
+				|RPA_CREDIT_ERR;
+			temp64 = readq(&bar0->rpa_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->rpa_err_mask);
+
+			val64 = RDA_RXDn_ECC_SG_ERR|RDA_RXDn_ECC_DB_ERR
+				|RDA_FRM_ECC_SG_ERR|RDA_FRM_ECC_DB_N_AERR
+				|RDA_SM1_ERR_ALARM|RDA_SM0_ERR_ALARM
+				|RDA_MISC_ERR|RDA_PCIX_ERR|RDA_RXD_ECC_DB_SERR;
+			temp64 = readq(&bar0->rda_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->rda_err_mask);
+
+			val64 = RTI_ECC_SG_ERR|RTI_ECC_DB_ERR|RTI_SM_ERR_ALARM;
+			temp64 = readq(&bar0->rti_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->rti_err_mask);
+		}
+	}
+
+	if (mask & RX_MAC_INTR) {
+		gen_int_mask |= RXMAC_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+			val64 = MAC_INT_STATUS_RMAC_INT;
+			temp64 = readq(&bar0->mac_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->mac_int_mask);
+
+			val64 = RMAC_RX_BUFF_OVRN|RMAC_RX_SM_ERR|
+				RMAC_UNUSED_INT|RMAC_SINGLE_ECC_ERR|
+				RMAC_DOUBLE_ECC_ERR|RMAC_LINK_STATE_CHANGE_INT;
+			temp64 = readq(&bar0->mac_rmac_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->mac_rmac_err_mask);
+		}
+		else {
+			val64 = MAC_INT_STATUS_RMAC_INT;
+			temp64 = readq(&bar0->mac_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mac_int_mask);
+
+			val64 = RMAC_RX_BUFF_OVRN|RMAC_FRM_RCVD_INT
+				|RMAC_UNUSED_INT|RMAC_SINGLE_ECC_ERR
+				|RMAC_DOUBLE_ECC_ERR|RMAC_LINK_STATE_CHANGE_INT
+				|RMAC_RX_SM_ERR;
+			temp64 = readq(&bar0->mac_rmac_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mac_rmac_err_mask);
+		}
+	}
+
+	if (mask & RX_XGXS_INTR)
+	{
+		gen_int_mask |= RXXGXS_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+			val64 = XGXS_INT_STATUS_RXGXS;
+			temp64 = readq(&bar0->xgxs_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->xgxs_int_mask);
+
+			val64 = RXGXS_ESTORE_OFLOW|RXGXS_RX_SM_ERR;
+			temp64 = readq(&bar0->xgxs_rxgxs_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->xgxs_rxgxs_err_mask);
+		}
+		else {
+			val64 = XGXS_INT_STATUS_RXGXS;
+			temp64 = readq(&bar0->xgxs_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->xgxs_int_mask);
+
+			val64 = RXGXS_ESTORE_OFLOW|RXGXS_RX_SM_ERR;
+			temp64 = readq(&bar0->xgxs_rxgxs_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->xgxs_rxgxs_err_mask);
+		}
+	}
+
+	if (mask & MC_INTR) {
+		gen_int_mask |= MC_INT_M;
+
+		if (flag == ENABLE_INTRS) {
+			val64 = MC_INT_MASK_MC_INT;
+			temp64 = readq(&bar0->mc_int_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->mc_int_mask);
+
+			val64 = MC_ERR_REG_SM_ERR|MC_ERR_REG_ECC_ALL_SNG|
+				MC_ERR_REG_ECC_ALL_DBL;
+			temp64 = readq(&bar0->mc_err_mask);
+			temp64 &= ~((u64) val64);
+			writeq(temp64, &bar0->mc_err_mask);
+		}
+		else {
+			val64 = MC_INT_MASK_MC_INT;
+			temp64 = readq(&bar0->mc_int_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mc_int_mask);
+
+			val64 = MC_ERR_REG_ECC_ALL_SNG|MC_ERR_REG_ECC_ALL_DBL
+				|MC_ERR_REG_SM_ERR|PLL_LOCK_N;
+			temp64 = readq(&bar0->mc_err_mask);
+			temp64 |= ((u64) val64);
+			writeq(temp64, &bar0->mc_err_mask);
+		}
+	}
+	nic->general_int_mask = gen_int_mask;
+
+	/* Remove this line when alarm interrupts are enabled */
+	nic->general_int_mask = 0;
+}
 /**
  *  en_dis_able_nic_intrs - Enable or Disable the interrupts
  *  @nic: device private variable,
@@ -1746,17 +2106,16 @@ static int s2io_link_fault_indication(st
 static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
 {
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
-	register u64 val64 = 0, temp64 = 0;
+	register u64 temp64 = 0, intr_mask = 0;
+
+	intr_mask = nic->general_int_mask;
 
 	/*  Top level interrupt classification */
 	/*  PIC Interrupts */
-	if ((mask & (TX_PIC_INTR | RX_PIC_INTR))) {
+	if (mask & TX_PIC_INTR) {
 		/*  Enable PIC Intrs in the general intr mask register */
-		val64 = TXPIC_INT_M;
+		intr_mask |= TXPIC_INT_M;
 		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
 			/*
 			 * If Hercules adapter enable GPIO otherwise
 			 * disable all PCIX, Flash, MDIO, IIC and GPIO
@@ -1771,58 +2130,21 @@ static void en_dis_able_nic_intrs(struct
 				temp64 = readq(&bar0->gpio_int_mask);
 				temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
 				writeq(temp64, &bar0->gpio_int_mask);
-			} else {
+			} else 
 				writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
-			}
-			/*
-			 * No MSI Support is available presently, so TTI and
-			 * RTI interrupts are also disabled.
-			 */
 		} else if (flag == DISABLE_INTRS) {
 			/*
 			 * Disable PIC Intrs in the general
 			 * intr mask register
 			 */
 			writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
-		}
-	}
-
-	/*  MAC Interrupts */
-	/*  Enabling/Disabling MAC interrupts */
-	if (mask & (TX_MAC_INTR | RX_MAC_INTR)) {
-		val64 = TXMAC_INT_M | RXMAC_INT_M;
-		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
-			/*
-			 * All MAC block error interrupts are disabled for now
-			 * TODO
-			 */
-		} else if (flag == DISABLE_INTRS) {
-			/*
-			 * Disable MAC Intrs in the general intr mask register
-			 */
-			writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);
-			writeq(DISABLE_ALL_INTRS,
-			       &bar0->mac_rmac_err_mask);
-
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
 		}
 	}
 
 	/*  Tx traffic interrupts */
 	if (mask & TX_TRAFFIC_INTR) {
-		val64 = TXTRAFFIC_INT_M;
+		intr_mask |= TXTRAFFIC_INT_M;
 		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
 			/*
 			 * Enable all the Tx side interrupts
 			 * writing 0 Enables all 64 TX interrupt levels
@@ -1834,19 +2156,13 @@ static void en_dis_able_nic_intrs(struct
 			 * register.
 			 */
 			writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask);
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
 		}
 	}
 
 	/*  Rx traffic interrupts */
 	if (mask & RX_TRAFFIC_INTR) {
-		val64 = RXTRAFFIC_INT_M;
+		intr_mask |= RXTRAFFIC_INT_M;
 		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
 			/* writing 0 Enables all 8 RX interrupt levels */
 			writeq(0x0, &bar0->rx_traffic_mask);
 		} else if (flag == DISABLE_INTRS) {
@@ -1855,11 +2171,17 @@ static void en_dis_able_nic_intrs(struct
 			 * register.
 			 */
 			writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask);
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
 		}
 	}
+
+	temp64 = readq(&bar0->general_int_mask);
+	if (flag == ENABLE_INTRS)
+		temp64 &= ~((u64) intr_mask);
+	else
+		temp64 = DISABLE_ALL_INTRS;
+	writeq(temp64, &bar0->general_int_mask);
+
+	nic->general_int_mask = readq(&bar0->general_int_mask);
 }
 
 /**
@@ -2063,14 +2385,6 @@ static int start_nic(struct s2io_nic *ni
 	writeq(val64, &bar0->adapter_control);
 
 	/*
-	 * Clearing any possible Link state change interrupts that
-	 * could have popped up just before Enabling the card.
-	 */
-	val64 = readq(&bar0->mac_rmac_err_reg);
-	if (val64)
-		writeq(val64, &bar0->mac_rmac_err_reg);
-
-	/*
 	 * Verify if the device is ready to be enabled, if so enable
 	 * it.
 	 */
@@ -2223,9 +2537,9 @@ static void stop_nic(struct s2io_nic *ni
 	config = &nic->config;
 
 	/*  Disable all interrupts */
+	en_dis_err_alarms(nic, ENA_ALL_INTRS, DISABLE_INTRS);
 	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-	interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-	interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+	interruptible |= TX_PIC_INTR;
 	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
 	/* Clearing Adapter_En bit of ADAPTER_CONTROL Register */
@@ -6670,12 +6984,12 @@ static int s2io_card_up(struct s2io_nic 
 	tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
 
 	/*  Enable select interrupts */
+	en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
 	if (sp->intr_type != INTA)
 		en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
 	else {
 		interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-		interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-		interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+		interruptible |= TX_PIC_INTR;
 		en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
 	}
 
diff -Nurp orig/drivers/net/s2io.h patch1/drivers/net/s2io.h
--- orig/drivers/net/s2io.h	2007-08-15 08:04:06.000000000 -0700
+++ patch1/drivers/net/s2io.h	2007-08-15 08:06:06.000000000 -0700
@@ -892,6 +892,7 @@ struct s2io_nic {
 
 	spinlock_t	rx_lock;
 	atomic_t	isr_cnt;
+	u64		general_int_mask;
 	u64 *ufo_in_band_v;
 #define VPD_STRING_LEN 80
 	u8  product_name[VPD_STRING_LEN];
diff -Nurp orig/drivers/net/s2io-regs.h patch1/drivers/net/s2io-regs.h
--- orig/drivers/net/s2io-regs.h	2007-08-15 08:04:06.000000000 -0700
+++ patch1/drivers/net/s2io-regs.h	2007-08-15 08:06:06.000000000 -0700
@@ -325,33 +325,66 @@ struct XENA_dev_config {
 #define TXDMA_TPA_INT                  BIT(5)
 #define TXDMA_SM_INT                   BIT(6)
 	u64 pfc_err_reg;
+#define PFC_ECC_SG_ERR			BIT(7)
+#define PFC_ECC_DB_ERR			BIT(15)
+#define PFC_SM_ERR_ALARM		BIT(23)
+#define PFC_MISC_0_ERR			BIT(31)
+#define PFC_MISC_1_ERR			BIT(32)
+#define PFC_PCIX_ERR			BIT(39)
 	u64 pfc_err_mask;
 	u64 pfc_err_alarm;
 
 	u64 tda_err_reg;
+#define TDA_Fn_ECC_SG_ERR		vBIT(0xff,0,8)
+#define TDA_Fn_ECC_DB_ERR		vBIT(0xff,8,8)
+#define TDA_SM0_ERR_ALARM		BIT(22)
+#define TDA_SM1_ERR_ALARM		BIT(23)
+#define TDA_PCIX_ERR			BIT(39)
 	u64 tda_err_mask;
 	u64 tda_err_alarm;
 
 	u64 pcc_err_reg;
-#define PCC_FB_ECC_DB_ERR		vBIT(0xFF, 16, 8)
+#define PCC_FB_ECC_SG_ERR		vBIT(0xFF,0,8)
+#define PCC_TXB_ECC_SG_ERR		vBIT(0xFF,8,8)
+#define PCC_FB_ECC_DB_ERR		vBIT(0xFF,16, 8)
+#define PCC_TXB_ECC_DB_ERR		vBIT(0xff,24,8)
+#define PCC_SM_ERR_ALARM		vBIT(0xff,32,8)
+#define PCC_WR_ERR_ALARM		vBIT(0xff,40,8)
+#define PCC_N_SERR			vBIT(0xff,48,8)
+#define PCC_6_COF_OV_ERR		BIT(56)
+#define PCC_7_COF_OV_ERR		BIT(57)
+#define PCC_6_LSO_OV_ERR		BIT(58)
+#define PCC_7_LSO_OV_ERR		BIT(59)
 #define PCC_ENABLE_FOUR			vBIT(0x0F,0,8)
-
 	u64 pcc_err_mask;
 	u64 pcc_err_alarm;
 
 	u64 tti_err_reg;
+#define TTI_ECC_SG_ERR			BIT(7)
+#define TTI_ECC_DB_ERR			BIT(15)
+#define TTI_SM_ERR_ALARM		BIT(23)
 	u64 tti_err_mask;
 	u64 tti_err_alarm;
 
 	u64 lso_err_reg;
+#define LSO6_SEND_OFLOW			BIT(12)
+#define LSO7_SEND_OFLOW			BIT(13)
+#define LSO6_ABORT			BIT(14)
+#define LSO7_ABORT			BIT(15)
+#define LSO6_SM_ERR_ALARM		BIT(22)
+#define LSO7_SM_ERR_ALARM		BIT(23)
 	u64 lso_err_mask;
 	u64 lso_err_alarm;
 
 	u64 tpa_err_reg;
+#define TPA_TX_FRM_DROP			BIT(7)
+#define TPA_SM_ERR_ALARM		BIT(23)
+
 	u64 tpa_err_mask;
 	u64 tpa_err_alarm;
 
 	u64 sm_err_reg;
+#define SM_SM_ERR_ALARM			BIT(15)
 	u64 sm_err_mask;
 	u64 sm_err_alarm;
 
@@ -450,22 +483,52 @@ struct XENA_dev_config {
 #define RXDMA_INT_RTI_INT_M            BIT(3)
 
 	u64 rda_err_reg;
+#define RDA_RXDn_ECC_SG_ERR		vBIT(0xFF,0,8)
+#define RDA_RXDn_ECC_DB_ERR		vBIT(0xFF,8,8)
+#define RDA_FRM_ECC_SG_ERR		BIT(23)
+#define RDA_FRM_ECC_DB_N_AERR		BIT(31)
+#define RDA_SM1_ERR_ALARM		BIT(38)
+#define RDA_SM0_ERR_ALARM		BIT(39)
+#define RDA_MISC_ERR			BIT(47)
+#define RDA_PCIX_ERR			BIT(55)
+#define RDA_RXD_ECC_DB_SERR		BIT(63)
 	u64 rda_err_mask;
 	u64 rda_err_alarm;
 
 	u64 rc_err_reg;
+#define RC_PRCn_ECC_SG_ERR		vBIT(0xFF,0,8)
+#define RC_PRCn_ECC_DB_ERR		vBIT(0xFF,8,8)
+#define RC_FTC_ECC_SG_ERR		BIT(23)
+#define RC_FTC_ECC_DB_ERR		BIT(31)
+#define RC_PRCn_SM_ERR_ALARM		vBIT(0xFF,32,8)
+#define RC_FTC_SM_ERR_ALARM		BIT(47)
+#define RC_RDA_FAIL_WR_Rn		vBIT(0xFF,48,8)
 	u64 rc_err_mask;
 	u64 rc_err_alarm;
 
 	u64 prc_pcix_err_reg;
+#define PRC_PCI_AB_RD_Rn		vBIT(0xFF,0,8)
+#define PRC_PCI_DP_RD_Rn		vBIT(0xFF,8,8)
+#define PRC_PCI_AB_WR_Rn		vBIT(0xFF,16,8)
+#define PRC_PCI_DP_WR_Rn		vBIT(0xFF,24,8)
+#define PRC_PCI_AB_F_WR_Rn		vBIT(0xFF,32,8)
+#define PRC_PCI_DP_F_WR_Rn		vBIT(0xFF,40,8)
 	u64 prc_pcix_err_mask;
 	u64 prc_pcix_err_alarm;
 
 	u64 rpa_err_reg;
+#define RPA_ECC_SG_ERR			BIT(7)
+#define RPA_ECC_DB_ERR			BIT(15)
+#define RPA_FLUSH_REQUEST		BIT(22)
+#define RPA_SM_ERR_ALARM		BIT(23)
+#define RPA_CREDIT_ERR			BIT(31)
 	u64 rpa_err_mask;
 	u64 rpa_err_alarm;
 
 	u64 rti_err_reg;
+#define RTI_ECC_SG_ERR			BIT(7)
+#define RTI_ECC_DB_ERR			BIT(15)
+#define RTI_SM_ERR_ALARM		BIT(23)
 	u64 rti_err_mask;
 	u64 rti_err_alarm;
 
@@ -582,17 +645,43 @@ struct XENA_dev_config {
 #define MAC_INT_STATUS_RMAC_INT            BIT(1)
 
 	u64 mac_tmac_err_reg;
-#define TMAC_ERR_REG_TMAC_ECC_DB_ERR       BIT(15)
-#define TMAC_ERR_REG_TMAC_TX_BUF_OVRN      BIT(23)
-#define TMAC_ERR_REG_TMAC_TX_CRI_ERR       BIT(31)
+#define TMAC_ECC_SG_ERR				BIT(7)
+#define TMAC_ECC_DB_ERR				BIT(15)
+#define TMAC_TX_BUF_OVRN			BIT(23)
+#define TMAC_TX_CRI_ERR				BIT(31)
+#define TMAC_TX_SM_ERR				BIT(39)
+#define TMAC_DESC_ECC_SG_ERR			BIT(47)
+#define TMAC_DESC_ECC_DB_ERR			BIT(55)
+
 	u64 mac_tmac_err_mask;
 	u64 mac_tmac_err_alarm;
 
 	u64 mac_rmac_err_reg;
-#define RMAC_ERR_REG_RX_BUFF_OVRN          BIT(0)
-#define RMAC_ERR_REG_RTS_ECC_DB_ERR        BIT(14)
-#define RMAC_ERR_REG_ECC_DB_ERR            BIT(15)
-#define RMAC_LINK_STATE_CHANGE_INT         BIT(31)
+#define RMAC_RX_BUFF_OVRN			BIT(0)
+#define RMAC_FRM_RCVD_INT			BIT(1)
+#define RMAC_UNUSED_INT				BIT(2)
+#define RMAC_RTS_PNUM_ECC_SG_ERR		BIT(5)
+#define RMAC_RTS_DS_ECC_SG_ERR			BIT(6)
+#define RMAC_RD_BUF_ECC_SG_ERR			BIT(7)
+#define RMAC_RTH_MAP_ECC_SG_ERR			BIT(8)
+#define RMAC_RTH_SPDM_ECC_SG_ERR		BIT(9)
+#define RMAC_RTS_VID_ECC_SG_ERR			BIT(10)
+#define RMAC_DA_SHADOW_ECC_SG_ERR		BIT(11)
+#define RMAC_RTS_PNUM_ECC_DB_ERR		BIT(13)
+#define RMAC_RTS_DS_ECC_DB_ERR			BIT(14)
+#define RMAC_RD_BUF_ECC_DB_ERR			BIT(15)
+#define RMAC_RTH_MAP_ECC_DB_ERR			BIT(16)
+#define RMAC_RTH_SPDM_ECC_DB_ERR		BIT(17)
+#define RMAC_RTS_VID_ECC_DB_ERR			BIT(18)
+#define RMAC_DA_SHADOW_ECC_DB_ERR		BIT(19)
+#define RMAC_LINK_STATE_CHANGE_INT		BIT(31)
+#define RMAC_RX_SM_ERR				BIT(39)
+#define RMAC_SINGLE_ECC_ERR			(BIT(5) | BIT(6) | BIT(7) |\
+						BIT(8)  | BIT(9) | BIT(10)|\
+						BIT(11))
+#define RMAC_DOUBLE_ECC_ERR			(BIT(13) | BIT(14) | BIT(15) |\
+						BIT(16)  | BIT(17) | BIT(18)|\
+						BIT(19))
 	u64 mac_rmac_err_mask;
 	u64 mac_rmac_err_alarm;
 
@@ -750,6 +839,7 @@ struct XENA_dev_config {
 					BIT(17) | BIT(19))
 #define MC_ERR_REG_ECC_ALL_DBL		   (BIT(10) | BIT(11) | BIT(12) |\
 					BIT(13) | BIT(18) | BIT(20))
+#define PLL_LOCK_N			BIT(39)
 	u64 mc_err_mask;
 	u64 mc_err_alarm;
 
@@ -823,11 +913,17 @@ struct XENA_dev_config {
 #define XGXS_INT_MASK_RXGXS                BIT(1)
 
 	u64 xgxs_txgxs_err_reg;
-#define TXGXS_ECC_DB_ERR                   BIT(15)
+#define TXGXS_ECC_SG_ERR		BIT(7)
+#define TXGXS_ECC_DB_ERR		BIT(15)
+#define TXGXS_ESTORE_UFLOW		BIT(31)
+#define TXGXS_TX_SM_ERR			BIT(39)
+
 	u64 xgxs_txgxs_err_mask;
 	u64 xgxs_txgxs_err_alarm;
 
 	u64 xgxs_rxgxs_err_reg;
+#define RXGXS_ESTORE_OFLOW		BIT(7)
+#define RXGXS_RX_SM_ERR			BIT(39)
 	u64 xgxs_rxgxs_err_mask;
 	u64 xgxs_rxgxs_err_alarm;
 




^ permalink raw reply

* [PATCH 2.6.24 2/5]S2io: Handle and monitor all of the device errors and alarms
From: Ramkrishna Vepa @ 2007-08-16  0:12 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Added support to poll entire set of device errors and alarams.
- Replaced alarm_intr_handler() with s2io_handle_errors().
- Added statistic counters to monitor the alarms.

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Santosh Rastapur <santosh.rastapur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -Nurp patch1/drivers/net/s2io.c patch2/drivers/net/s2io.c
--- patch1/drivers/net/s2io.c	2007-08-15 08:55:53.000000000 -0700
+++ patch2/drivers/net/s2io.c	2007-08-15 08:57:44.000000000 -0700
@@ -263,7 +263,14 @@ static char ethtool_driver_stats_keys[][
 	{"serious_err_cnt"},
 	{"soft_reset_cnt"},
 	{"fifo_full_cnt"},
-	{"ring_full_cnt"},
+	{"ring_0_full_cnt"},
+	{"ring_1_full_cnt"},
+	{"ring_2_full_cnt"},
+	{"ring_3_full_cnt"},
+	{"ring_4_full_cnt"},
+	{"ring_5_full_cnt"},
+	{"ring_6_full_cnt"},
+	{"ring_7_full_cnt"},
 	("alarm_transceiver_temp_high"),
 	("alarm_transceiver_temp_low"),
 	("alarm_laser_bias_current_high"),
@@ -303,7 +310,24 @@ static char ethtool_driver_stats_keys[][
 	("rx_tcode_fcs_err_cnt"),
 	("rx_tcode_buf_size_err_cnt"),
 	("rx_tcode_rxd_corrupt_cnt"),
-	("rx_tcode_unkn_err_cnt")
+	("rx_tcode_unkn_err_cnt"),
+	{"tda_err_cnt"},
+	{"pfc_err_cnt"},
+	{"pcc_err_cnt"},
+	{"tti_err_cnt"},
+	{"tpa_err_cnt"},
+	{"sm_err_cnt"},
+	{"lso_err_cnt"},
+	{"mac_tmac_err_cnt"},
+	{"mac_rmac_err_cnt"},
+	{"xgxs_txgxs_err_cnt"},
+	{"xgxs_rxgxs_err_cnt"},
+	{"rc_err_cnt"},
+	{"prc_pcix_err_cnt"},
+	{"rpa_err_cnt"},
+	{"rda_err_cnt"},
+	{"rti_err_cnt"},
+	{"mc_err_cnt"}
 };
 
 #define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN
@@ -3478,135 +3502,6 @@ static void s2io_updt_xpak_counter(struc
 }
 
 /**
- *  alarm_intr_handler - Alarm Interrrupt handler
- *  @nic: device private variable
- *  Description: If the interrupt was neither because of Rx packet or Tx
- *  complete, this function is called. If the interrupt was to indicate
- *  a loss of link, the OSM link status handler is invoked for any other
- *  alarm interrupt the block that raised the interrupt is displayed
- *  and a H/W reset is issued.
- *  Return Value:
- *  NONE
-*/
-
-static void alarm_intr_handler(struct s2io_nic *nic)
-{
-	struct net_device *dev = (struct net_device *) nic->dev;
-	struct XENA_dev_config __iomem *bar0 = nic->bar0;
-	register u64 val64 = 0, err_reg = 0;
-	u64 cnt;
-	int i;
-	if (atomic_read(&nic->card_state) == CARD_DOWN)
-		return;
-	if (pci_channel_offline(nic->pdev))
-		return;
-	nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
-	/* Handling the XPAK counters update */
-	if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
-		/* waiting for an hour */
-		nic->mac_control.stats_info->xpak_stat.xpak_timer_count++;
-	} else {
-		s2io_updt_xpak_counter(dev);
-		/* reset the count to zero */
-		nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0;
-	}
-
-	/* Handling link status change error Intr */
-	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
-		err_reg = readq(&bar0->mac_rmac_err_reg);
-		writeq(err_reg, &bar0->mac_rmac_err_reg);
-		if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
-			schedule_work(&nic->set_link_task);
-		}
-	}
-
-	/* Handling Ecc errors */
-	val64 = readq(&bar0->mc_err_reg);
-	writeq(val64, &bar0->mc_err_reg);
-	if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
-		if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
-			nic->mac_control.stats_info->sw_stat.
-				double_ecc_errs++;
-			DBG_PRINT(INIT_DBG, "%s: Device indicates ",
-				  dev->name);
-			DBG_PRINT(INIT_DBG, "double ECC error!!\n");
-			if (nic->device_type != XFRAME_II_DEVICE) {
-				/* Reset XframeI only if critical error */
-				if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
-					     MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
-					netif_stop_queue(dev);
-					schedule_work(&nic->rst_timer_task);
-					nic->mac_control.stats_info->sw_stat.
-							soft_reset_cnt++;
-				}
-			}
-		} else {
-			nic->mac_control.stats_info->sw_stat.
-				single_ecc_errs++;
-		}
-	}
-
-	/* In case of a serious error, the device will be Reset. */
-	val64 = readq(&bar0->serr_source);
-	if (val64 & SERR_SOURCE_ANY) {
-		nic->mac_control.stats_info->sw_stat.serious_err_cnt++;
-		DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
-		DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
-			  (unsigned long long)val64);
-		netif_stop_queue(dev);
-		schedule_work(&nic->rst_timer_task);
-		nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
-	}
-
-	/*
-	 * Also as mentioned in the latest Errata sheets if the PCC_FB_ECC
-	 * Error occurs, the adapter will be recycled by disabling the
-	 * adapter enable bit and enabling it again after the device
-	 * becomes Quiescent.
-	 */
-	val64 = readq(&bar0->pcc_err_reg);
-	writeq(val64, &bar0->pcc_err_reg);
-	if (val64 & PCC_FB_ECC_DB_ERR) {
-		u64 ac = readq(&bar0->adapter_control);
-		ac &= ~(ADAPTER_CNTL_EN);
-		writeq(ac, &bar0->adapter_control);
-		ac = readq(&bar0->adapter_control);
-		schedule_work(&nic->set_link_task);
-	}
-	/* Check for data parity error */
-	val64 = readq(&bar0->pic_int_status);
-	if (val64 & PIC_INT_GPIO) {
-		val64 = readq(&bar0->gpio_int_reg);
-		if (val64 & GPIO_INT_REG_DP_ERR_INT) {
-			nic->mac_control.stats_info->sw_stat.parity_err_cnt++;
-			schedule_work(&nic->rst_timer_task);
-			nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
-		}
-	}
-
-	/* Check for ring full counter */
-	if (nic->device_type & XFRAME_II_DEVICE) {
-		val64 = readq(&bar0->ring_bump_counter1);
-		for (i=0; i<4; i++) {
-			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
-			cnt >>= 64 - ((i+1)*16);
-			nic->mac_control.stats_info->sw_stat.ring_full_cnt
-				+= cnt;
-		}
-
-		val64 = readq(&bar0->ring_bump_counter2);
-		for (i=0; i<4; i++) {
-			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
-			cnt >>= 64 - ((i+1)*16);
-			nic->mac_control.stats_info->sw_stat.ring_full_cnt
-				+= cnt;
-		}
-	}
-
-	/* Other type of interrupts are not being handled now,  TODO */
-}
-
-/**
  *  wait_for_cmd_complete - waits for a command to complete.
  *  @sp : private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
@@ -4468,8 +4363,9 @@ static void
 s2io_alarm_handle(unsigned long data)
 {
 	struct s2io_nic *sp = (struct s2io_nic *)data;
+	struct net_device *dev = sp->dev;
 
-	alarm_intr_handler(sp);
+	s2io_handle_errors(dev);
 	mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
@@ -4588,6 +4484,391 @@ static void s2io_txpic_intr_handle(struc
 }
 
 /**
+ *  s2io_handle_errors - Xframe error indication handler
+ *  @nic: device private variable
+ *  Description: Handle alarms such as loss of link, single or
+ *  double ECC errors, critical and serious errors.
+ *  Return Value:
+ *  NONE
+ */
+static void s2io_handle_errors(void * dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct s2io_nic *sp = dev->priv;
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+	u64 temp64 = 0,val64=0;
+	int i = 0;
+
+	struct swStat *sw_stat = &sp->mac_control.stats_info->sw_stat;
+	struct xpakStat *stats = &sp->mac_control.stats_info->xpak_stat;
+
+	if (unlikely(atomic_read(&sp->card_state) == CARD_DOWN))
+		return;
+
+	if (pci_channel_offline(sp->pdev))
+		return;
+
+	memset(&sw_stat->ring_full_cnt, 0,
+		sizeof(sw_stat->ring_full_cnt));
+
+	/* Handling the XPAK counters update */
+	if(stats->xpak_timer_count < 72000) {
+		/* waiting for an hour */
+		stats->xpak_timer_count++;
+	} else {
+		s2io_updt_xpak_counter(dev);
+		/* reset the count to zero */
+		stats->xpak_timer_count = 0;
+	}
+
+	/* Handling link status change error Intr */
+	if (s2io_link_fault_indication(sp) == MAC_RMAC_ERR_TIMER) {
+		val64 = readq(&bar0->mac_rmac_err_reg);
+		writeq(val64, &bar0->mac_rmac_err_reg);
+		if (val64 & RMAC_LINK_STATE_CHANGE_INT)
+			schedule_work(&sp->set_link_task);
+	}
+
+	/* In case of a serious error, the device will be Reset. */
+	val64 = readq(&bar0->serr_source);
+	if (val64 & SERR_SOURCE_ANY) {
+		sw_stat->serious_err_cnt++;
+		goto reset;
+	}
+
+	/* Check for data parity error */
+	val64 = readq(&bar0->gpio_int_reg);
+	if (val64 & GPIO_INT_REG_DP_ERR_INT) {
+		sw_stat->parity_err_cnt++;
+		goto reset;
+	}
+
+	/* Check for ring full counter */
+	if (sp->device_type == XFRAME_II_DEVICE) {
+		val64 = readq(&bar0->ring_bump_counter1);
+		for (i=0; i<4; i++) {
+			temp64 = ( val64 & vBIT(0xFFFF,(i*16),16));
+			temp64 >>= 64 - ((i+1)*16);
+			sw_stat->ring_full_cnt[i] += temp64;
+		}
+
+		val64 = readq(&bar0->ring_bump_counter2);
+		for (i=0; i<4; i++) {
+			temp64 = ( val64 & vBIT(0xFFFF,(i*16),16));
+			temp64 >>= 64 - ((i+1)*16);
+			 sw_stat->ring_full_cnt[i+4] += temp64;
+		}
+	}
+
+	val64 = readq(&bar0->txdma_int_status);
+	/*check for pfc_err*/
+	if (val64 & TXDMA_PFC_INT) {
+		val64 = readq(&bar0->pfc_err_reg);
+		temp64 = PFC_ECC_DB_ERR | PFC_SM_ERR_ALARM
+			| PFC_MISC_0_ERR | PFC_MISC_1_ERR
+			| PFC_PCIX_ERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->pfc_err_reg);
+			sw_stat->pfc_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = PFC_ECC_SG_ERR;
+		if (val64 & temp64) {
+			sw_stat->pfc_err_cnt++;
+			writeq(val64, &bar0->pfc_err_reg);
+		}
+	}
+
+	/*check for tda_err*/
+	if (val64 & TXDMA_TDA_INT) {
+		val64 = readq(&bar0->tda_err_reg);
+		temp64 = TDA_Fn_ECC_DB_ERR | TDA_SM0_ERR_ALARM
+			| TDA_SM1_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->tda_err_reg);
+			sw_stat->tda_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = TDA_Fn_ECC_SG_ERR | TDA_PCIX_ERR;
+		if (val64 & temp64) {
+			sw_stat->tda_err_cnt++;
+			writeq(val64, &bar0->tda_err_reg);
+		}
+	}
+	/*check for pcc_err*/
+	if (val64 & TXDMA_PCC_INT) {
+		val64 = readq(&bar0->pcc_err_reg);
+		temp64 = PCC_TXB_ECC_DB_ERR
+			| PCC_SM_ERR_ALARM | PCC_WR_ERR_ALARM
+			| PCC_N_SERR | PCC_6_COF_OV_ERR
+			| PCC_7_COF_OV_ERR | PCC_6_LSO_OV_ERR
+			| PCC_7_LSO_OV_ERR | PCC_FB_ECC_DB_ERR
+			| PCC_TXB_ECC_DB_ERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->pcc_err_reg);
+			sw_stat->pcc_err_cnt++;
+			goto reset;
+		}
+
+		if (val64 & (PCC_FB_ECC_SG_ERR | PCC_TXB_ECC_SG_ERR)) {
+			sw_stat->pcc_err_cnt++;
+			writeq(val64, &bar0->pcc_err_reg);
+		}
+	}
+
+	/*check for tti_err*/
+	if (val64 & TXDMA_TTI_INT) {
+		val64 = readq(&bar0->tti_err_reg);
+		temp64 = TTI_SM_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->tti_err_reg);
+			sw_stat->tti_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = TTI_ECC_SG_ERR | TTI_ECC_DB_ERR;
+		if (val64 & temp64) {
+			sw_stat->tti_err_cnt++;
+			writeq(val64, &bar0->tti_err_reg);
+		}
+	}
+
+	/*check for lso_err*/
+	if (val64 & TXDMA_LSO_INT) {
+		val64 = readq(&bar0->lso_err_reg);
+		temp64 = LSO6_ABORT | LSO7_ABORT
+			| LSO6_SM_ERR_ALARM | LSO7_SM_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->lso_err_reg);
+			sw_stat->lso_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = LSO6_SEND_OFLOW | LSO7_SEND_OFLOW;
+		if (val64 & temp64) {
+			sw_stat->lso_err_cnt++;
+			writeq(val64, &bar0->lso_err_reg);
+		}
+	}
+
+	/*check for tpa_err*/
+	if (val64 & TXDMA_TPA_INT) {
+		val64 = readq(&bar0->tpa_err_reg);
+		temp64 = TPA_SM_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->tpa_err_reg);
+			sw_stat->tpa_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = TPA_TX_FRM_DROP;
+		if (val64 & temp64) {
+			sw_stat->tpa_err_cnt++;
+			writeq(val64, &bar0->tpa_err_reg);
+		}
+	}
+
+	/*check for sm_err*/
+	if (val64 & TXDMA_SM_INT) {
+		val64 = readq(&bar0->sm_err_reg);
+		temp64 = SM_SM_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->sm_err_reg);
+			sw_stat->sm_err_cnt++;
+			goto reset;
+		}
+	}
+
+	val64 = readq(&bar0->mac_int_status);
+	if (val64 & MAC_INT_STATUS_TMAC_INT) {
+		val64 = readq(&bar0->mac_tmac_err_reg);
+		temp64 = TMAC_TX_BUF_OVRN | TMAC_TX_SM_ERR;
+		if ( val64 & temp64) {
+			writeq(val64, &bar0->mac_tmac_err_reg);
+			sw_stat->mac_tmac_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = TMAC_ECC_SG_ERR | TMAC_ECC_DB_ERR
+			| TMAC_DESC_ECC_SG_ERR | TMAC_DESC_ECC_DB_ERR;
+		if (val64 & temp64) {
+			sw_stat->mac_tmac_err_cnt++;
+			writeq(val64, &bar0->mac_tmac_err_reg);
+		}
+	}
+
+	val64 = readq(&bar0->xgxs_int_status);
+	if (val64 & XGXS_INT_STATUS_TXGXS) {
+		val64 = readq(&bar0->xgxs_txgxs_err_reg);
+		temp64 = TXGXS_ESTORE_UFLOW | TXGXS_TX_SM_ERR;
+		if ( val64 & temp64) {
+			writeq(val64, &bar0->xgxs_txgxs_err_reg);
+			sw_stat->xgxs_txgxs_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = TXGXS_ECC_SG_ERR | TXGXS_ECC_DB_ERR;
+		if (val64 & temp64) {
+			sw_stat->xgxs_txgxs_err_cnt++;
+			writeq(val64, &bar0->xgxs_txgxs_err_reg);
+		}
+	}
+
+	val64 = readq(&bar0->rxdma_int_status);
+	if (val64 & RXDMA_INT_RC_INT_M) {
+		val64 = readq(&bar0->rc_err_reg);
+		temp64 = RC_PRCn_ECC_DB_ERR | RC_FTC_ECC_DB_ERR
+			| RC_PRCn_SM_ERR_ALARM |RC_FTC_SM_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->rc_err_reg);
+			sw_stat->rc_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = RC_PRCn_ECC_SG_ERR | RC_FTC_ECC_SG_ERR
+			| RC_RDA_FAIL_WR_Rn;
+		if (val64 & temp64) {
+			sw_stat->rc_err_cnt++;
+			writeq(val64, &bar0->rc_err_reg);
+		}
+
+		val64 = readq(&bar0->prc_pcix_err_reg);
+		temp64 = PRC_PCI_AB_RD_Rn | PRC_PCI_AB_WR_Rn
+			| PRC_PCI_AB_F_WR_Rn;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->prc_pcix_err_reg);
+			sw_stat->prc_pcix_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = PRC_PCI_DP_RD_Rn | PRC_PCI_DP_WR_Rn
+			| PRC_PCI_DP_F_WR_Rn;
+		if (val64 & temp64) {
+			sw_stat->prc_pcix_err_cnt++;
+			writeq(val64, &bar0->prc_pcix_err_reg);
+		}
+	}
+
+	if (val64 & RXDMA_INT_RPA_INT_M) {
+		val64 = readq(&bar0->rpa_err_reg);
+		temp64 = RPA_SM_ERR_ALARM | RPA_CREDIT_ERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->rpa_err_reg);
+			sw_stat->rpa_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = RPA_ECC_SG_ERR | RPA_ECC_DB_ERR;
+		if (val64 & temp64) {
+			sw_stat->rpa_err_cnt++;
+			writeq(val64, &bar0->rpa_err_reg);
+		}
+	}
+
+	if (val64 & RXDMA_INT_RDA_INT_M) {
+		val64 = readq(&bar0->rda_err_reg);
+		temp64 = RDA_RXDn_ECC_DB_ERR | RDA_FRM_ECC_DB_N_AERR
+			| RDA_SM1_ERR_ALARM | RDA_SM0_ERR_ALARM
+			| RDA_RXD_ECC_DB_SERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->rda_err_reg);
+			sw_stat->rda_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = RDA_RXDn_ECC_SG_ERR | RDA_FRM_ECC_SG_ERR
+			| RDA_MISC_ERR | RDA_PCIX_ERR;
+		if (val64 & temp64) {
+			sw_stat->rda_err_cnt++;
+			writeq(val64, &bar0->rda_err_reg);
+		}
+	}
+
+	if (val64 & RXDMA_INT_RTI_INT_M) {
+		val64 = readq(&bar0->rti_err_reg);
+		temp64 = RTI_SM_ERR_ALARM;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->rti_err_reg);
+			sw_stat->rti_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = RTI_ECC_SG_ERR | RTI_ECC_DB_ERR;
+		if (val64 & temp64) {
+			sw_stat->rti_err_cnt++;
+			writeq(val64, &bar0->rti_err_reg);
+		}
+	}
+
+	val64 = readq(&bar0->mac_int_status);
+	if (val64 & MAC_INT_STATUS_RMAC_INT) {
+		val64 = readq(&bar0->mac_rmac_err_reg);
+		temp64 = RMAC_RX_BUFF_OVRN | RMAC_RX_SM_ERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->mac_rmac_err_reg);
+			sw_stat->mac_rmac_err_cnt++;
+			goto reset;
+		}
+
+		temp64 = RMAC_UNUSED_INT|RMAC_SINGLE_ECC_ERR|
+			RMAC_DOUBLE_ECC_ERR;
+		if (val64 & temp64) {
+			sw_stat->mac_rmac_err_cnt++;
+			writeq(val64, &bar0->mac_rmac_err_reg);
+		}
+	}
+
+	val64 = readq(&bar0->xgxs_int_status);
+	if (val64 & XGXS_INT_STATUS_RXGXS) {
+		val64 = readq(&bar0->xgxs_rxgxs_err_reg);
+		temp64 = RXGXS_ESTORE_OFLOW | RXGXS_RX_SM_ERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->xgxs_rxgxs_err_reg);
+			sw_stat->xgxs_rxgxs_err_cnt++;
+			goto reset;
+		}
+	}
+
+	val64 = readq(&bar0->mc_int_status);
+	if(val64 & MC_INT_STATUS_MC_INT) {
+		val64 = readq(&bar0->mc_err_reg);
+		temp64 = MC_ERR_REG_SM_ERR;
+		if ( val64 & temp64 ) {
+			writeq(val64, &bar0->mc_err_reg);
+			sw_stat->mc_err_cnt++;
+			goto reset;
+		}
+
+		/* Handling Ecc errors */
+		if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
+			writeq(val64, &bar0->mc_err_reg);
+			if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
+				sw_stat->double_ecc_errs++;
+				if (sp->device_type != XFRAME_II_DEVICE) {
+					/*
+					 * Reset XframeI only if critical error
+					 */
+					if (val64 &
+						(MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
+						MC_ERR_REG_MIRI_ECC_DB_ERR_1))
+								goto reset;
+					}
+			} else
+				sw_stat->single_ecc_errs++;
+		}
+	}
+	return;
+
+reset:
+	netif_stop_queue(dev);
+	schedule_work(&sp->rst_timer_task);
+	sw_stat->soft_reset_cnt++;
+	return;
+}
+
+/**
  *  s2io_isr - ISR handler of the device .
  *  @irq: the irq of the device.
  *  @dev_id: a void pointer to the dev structure of the NIC.
@@ -5976,7 +6257,7 @@ static void s2io_get_ethtool_stats(struc
 				   struct ethtool_stats *estats,
 				   u64 * tmp_stats)
 {
-	int i = 0;
+	int i = 0, k;
 	struct s2io_nic *sp = dev->priv;
 	struct stat_block *stat_info = sp->mac_control.stats_info;
 
@@ -6171,7 +6452,8 @@ static void s2io_get_ethtool_stats(struc
 	tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt;
 	tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt;
 	tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt;
+	for (k = 0; k < MAX_RX_RINGS; k++)
+		tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt[k];
 	tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high;
 	tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low;
 	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high;
@@ -6228,6 +6510,23 @@ static void s2io_get_ethtool_stats(struc
 	tmp_stats[i++] = stat_info->sw_stat.rx_buf_size_err_cnt;
 	tmp_stats[i++] = stat_info->sw_stat.rx_rxd_corrupt_cnt;
 	tmp_stats[i++] = stat_info->sw_stat.rx_unkn_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.tda_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.pfc_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.pcc_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.tti_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.tpa_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.sm_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.lso_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.mac_tmac_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.mac_rmac_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.xgxs_txgxs_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.xgxs_rxgxs_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.rc_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.prc_pcix_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.rpa_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.rda_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.rti_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.mc_err_cnt;
 }
 
 static int s2io_ethtool_get_regs_len(struct net_device *dev)
diff -Nurp patch1/drivers/net/s2io.h patch2/drivers/net/s2io.h
--- patch1/drivers/net/s2io.h	2007-08-15 08:06:06.000000000 -0700
+++ patch2/drivers/net/s2io.h	2007-08-15 08:06:17.000000000 -0700
@@ -91,7 +91,7 @@ struct swStat {
 	unsigned long long serious_err_cnt;
 	unsigned long long soft_reset_cnt;
 	unsigned long long fifo_full_cnt;
-	unsigned long long ring_full_cnt;
+	unsigned long long ring_full_cnt[8];
 	/* LRO statistics */
 	unsigned long long clubbed_frms_cnt;
 	unsigned long long sending_both;
@@ -126,6 +126,26 @@ struct swStat {
 	unsigned long long rx_buf_size_err_cnt;
 	unsigned long long rx_rxd_corrupt_cnt;
 	unsigned long long rx_unkn_err_cnt;
+
+	/* Error/alarm statistics*/
+	unsigned long long tda_err_cnt;
+	unsigned long long pfc_err_cnt;
+	unsigned long long pcc_err_cnt;
+	unsigned long long tti_err_cnt;
+	unsigned long long lso_err_cnt;
+	unsigned long long tpa_err_cnt;
+	unsigned long long sm_err_cnt;
+	unsigned long long mac_tmac_err_cnt;
+	unsigned long long mac_rmac_err_cnt;
+	unsigned long long xgxs_txgxs_err_cnt;
+	unsigned long long xgxs_rxgxs_err_cnt;
+	unsigned long long rc_err_cnt;
+	unsigned long long prc_pcix_err_cnt;
+	unsigned long long rpa_err_cnt;
+	unsigned long long rda_err_cnt;
+	unsigned long long rti_err_cnt;
+	unsigned long long mc_err_cnt;
+
 };
 
 /* Xpak releated alarm and warnings */
@@ -1017,7 +1037,7 @@ static void free_shared_mem(struct s2io_
 static int init_nic(struct s2io_nic *nic);
 static void rx_intr_handler(struct ring_info *ring_data);
 static void tx_intr_handler(struct fifo_info *fifo_data);
-static void alarm_intr_handler(struct s2io_nic *sp);
+static void s2io_handle_errors(void * dev_id);
 
 static int s2io_starter(void);
 static void s2io_closer(void);




^ permalink raw reply

* [PATCH 2.6.24 3/5]S2io: Cleanup - removed unused variable, intr_type
From: Ramkrishna Vepa @ 2007-08-16  0:12 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Removed the unused variable, intr_type, in device private structure.

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Santosh Rastapur <santosh.rastapur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -Nurp patch2/drivers/net/s2io.c patch3/drivers/net/s2io.c
--- patch2/drivers/net/s2io.c	2007-08-15 08:57:44.000000000 -0700
+++ patch3/drivers/net/s2io.c	2007-08-15 08:57:32.000000000 -0700
@@ -1611,7 +1611,7 @@ static int init_nic(struct s2io_nic *nic
 
 		val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
 		    RTI_DATA2_MEM_RX_UFC_B(0x2) ;
-		if (nic->intr_type == MSI_X)
+		if (nic->config.intr_type == MSI_X)
 		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
 				RTI_DATA2_MEM_RX_UFC_D(0x40));
 		else
@@ -1749,7 +1749,7 @@ static int init_nic(struct s2io_nic *nic
 
 static int s2io_link_fault_indication(struct s2io_nic *nic)
 {
-	if (nic->intr_type != INTA)
+	if (nic->config.intr_type != INTA)
 		return MAC_RMAC_ERR_TIMER;
 	if (nic->device_type == XFRAME_II_DEVICE)
 		return LINK_UP_DOWN_INTERRUPT;
@@ -3774,7 +3774,7 @@ static int s2io_set_swapper(struct s2io_
 		 SWAPPER_CTRL_RXF_W_FE |
 		 SWAPPER_CTRL_XMSI_FE |
 		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
-	if (sp->intr_type == INTA)
+	if (sp->config.intr_type == INTA)
 		val64 |= SWAPPER_CTRL_XMSI_SE;
 	writeq(val64, &bar0->swapper_ctrl);
 #else
@@ -3797,7 +3797,7 @@ static int s2io_set_swapper(struct s2io_
 		 SWAPPER_CTRL_RXF_W_FE |
 		 SWAPPER_CTRL_XMSI_FE |
 		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
-	if (sp->intr_type == INTA)
+	if (sp->config.intr_type == INTA)
 		val64 |= SWAPPER_CTRL_XMSI_SE;
 	writeq(val64, &bar0->swapper_ctrl);
 #endif
@@ -4071,7 +4071,7 @@ static int s2io_open(struct net_device *
 	netif_carrier_off(dev);
 	sp->last_link_state = 0;
 
-	if (sp->intr_type == MSI_X) {
+	if (sp->config.intr_type == MSI_X) {
 		int ret = s2io_enable_msi_x(sp);
 
 		if (!ret) {
@@ -4103,12 +4103,12 @@ static int s2io_open(struct net_device *
 			DBG_PRINT(ERR_DBG,
 			  "%s: MSI-X requested but failed to enable\n",
 			  dev->name);
-			sp->intr_type = INTA;
+			sp->config.intr_type = INTA;
 		}
 	}
 
 	/* NAPI doesn't work well with MSI(X) */
-	 if (sp->intr_type != INTA) {
+	 if (sp->config.intr_type != INTA) {
 		if(sp->config.napi)
 			sp->config.napi = 0;
 	}
@@ -4132,7 +4132,7 @@ static int s2io_open(struct net_device *
 	return 0;
 
 hw_init_failed:
-	if (sp->intr_type == MSI_X) {
+	if (sp->config.intr_type == MSI_X) {
 		if (sp->entries) {
 			kfree(sp->entries);
 			sp->mac_control.stats_info->sw_stat.mem_freed 
@@ -7017,18 +7017,18 @@ static int s2io_add_isr(struct s2io_nic 
 	struct net_device *dev = sp->dev;
 	int err = 0;
 
-	if (sp->intr_type == MSI_X)
+	if (sp->config.intr_type == MSI_X)
 		ret = s2io_enable_msi_x(sp);
 	if (ret) {
 		DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
-		sp->intr_type = INTA;
+		sp->config.intr_type = INTA;
 	}
 
 	/* Store the values of the MSIX table in the struct s2io_nic structure */
 	store_xmsi_data(sp);
 
 	/* After proper initialization of H/W, register ISR */
-	if (sp->intr_type == MSI_X) {
+	if (sp->config.intr_type == MSI_X) {
 		int i, msix_tx_cnt=0,msix_rx_cnt=0;
 
 		for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
@@ -7080,7 +7080,7 @@ static int s2io_add_isr(struct s2io_nic 
 		printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
 		printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
 	}
-	if (sp->intr_type == INTA) {
+	if (sp->config.intr_type == INTA) {
 		err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
 				sp->name, dev);
 		if (err) {
@@ -7097,7 +7097,7 @@ static void s2io_rem_isr(struct s2io_nic
 	struct net_device *dev = sp->dev;
 	struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
 
-	if (sp->intr_type == MSI_X) {
+	if (sp->config.intr_type == MSI_X) {
 		int i;
 		u16 msi_control;
 
@@ -7270,7 +7270,7 @@ static int s2io_card_up(struct s2io_nic 
 
 	/* Add interrupt service routine */
 	if (s2io_add_isr(sp) != 0) {
-		if (sp->intr_type == MSI_X)
+		if (sp->config.intr_type == MSI_X)
 			s2io_rem_isr(sp);
 		s2io_reset(sp);
 		free_rx_buffers(sp);
@@ -7284,7 +7284,7 @@ static int s2io_card_up(struct s2io_nic 
 
 	/*  Enable select interrupts */
 	en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
-	if (sp->intr_type != INTA)
+	if (sp->config.intr_type != INTA)
 		en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
 	else {
 		interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
@@ -7811,7 +7811,7 @@ s2io_init_nic(struct pci_dev *pdev, cons
 	if (rx_ring_mode == 2)
 		sp->rxd_mode = RXD_MODE_3B;
 
-	sp->intr_type = dev_intr_type;
+	sp->config.intr_type = dev_intr_type;
 
 	if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
 		(pdev->device == PCI_DEVICE_ID_HERC_UNI))
@@ -8091,7 +8091,7 @@ s2io_init_nic(struct pci_dev *pdev, cons
 
 	if (napi)
 		DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
-	switch(sp->intr_type) {
+	switch(sp->config.intr_type) {
 		case INTA:
 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
 		    break;
diff -Nurp patch2/drivers/net/s2io.h patch3/drivers/net/s2io.h
--- patch2/drivers/net/s2io.h	2007-08-15 08:06:17.000000000 -0700
+++ patch3/drivers/net/s2io.h	2007-08-15 08:06:22.000000000 -0700
@@ -905,11 +905,6 @@ struct s2io_nic {
 	unsigned long	sending_both;
 	u8		lro;
 	u16		lro_max_aggr_per_sess;
-
-#define INTA	0
-#define MSI_X	2
-	u8 intr_type;
-
 	spinlock_t	rx_lock;
 	atomic_t	isr_cnt;
 	u64		general_int_mask;




^ permalink raw reply

* [PATCH 2.6.24 4/5]S2io: Check for CARD_DOWN before handling traffic
From: Ramkrishna Vepa @ 2007-08-16  0:12 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Added check to return from the traffic handling function, if the card status 
  is DOWN.

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Santosh Rastapur <santosh.rastapur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -Nurp patch3/drivers/net/s2io.c patch4/drivers/net/s2io.c
--- patch3/drivers/net/s2io.c	2007-08-15 08:57:32.000000000 -0700
+++ patch4/drivers/net/s2io.c	2007-08-15 08:42:14.000000000 -0700
@@ -2927,6 +2927,11 @@ static int s2io_poll(struct net_device *
 	int i;
 
 	atomic_inc(&nic->isr_cnt);
+	if (unlikely(atomic_read(&nic->card_state) == CARD_DOWN)) {
+		atomic_dec(&nic->isr_cnt);
+		return IRQ_NONE;
+	}
+
 	mac_control = &nic->mac_control;
 	config = &nic->config;
 
@@ -3062,12 +3067,6 @@ static void rx_intr_handler(struct ring_
 	struct RxD3* rxdp3;
 
 	spin_lock(&nic->rx_lock);
-	if (atomic_read(&nic->card_state) == CARD_DOWN) {
-		DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
-			  __FUNCTION__, dev->name);
-		spin_unlock(&nic->rx_lock);
-		return;
-	}
 
 	get_info = ring_data->rx_curr_get_info;
 	get_block = get_info.block_index;
@@ -4404,6 +4403,10 @@ static irqreturn_t s2io_msix_ring_handle
 	struct s2io_nic *sp = ring->nic;
 
 	atomic_inc(&sp->isr_cnt);
+	if (unlikely(atomic_read(&sp->card_state) == CARD_DOWN)){
+		atomic_dec(&sp->isr_cnt);
+		return IRQ_HANDLED;
+	}
 
 	rx_intr_handler(ring);
 	s2io_chk_rx_buffers(sp, ring->ring_no);
@@ -4418,6 +4421,10 @@ static irqreturn_t s2io_msix_fifo_handle
 	struct s2io_nic *sp = fifo->nic;
 
 	atomic_inc(&sp->isr_cnt);
+	if (unlikely(atomic_read(&sp->card_state) == CARD_DOWN)){
+		atomic_dec(&sp->isr_cnt);
+		return IRQ_HANDLED;
+	}
 	tx_intr_handler(fifo);
 	atomic_dec(&sp->isr_cnt);
 	return IRQ_HANDLED;
@@ -4896,6 +4903,11 @@ static irqreturn_t s2io_isr(int irq, voi
 		return IRQ_NONE;
 
 	atomic_inc(&sp->isr_cnt);
+	if (unlikely(atomic_read(&sp->card_state) == CARD_DOWN)) {
+		atomic_dec(&sp->isr_cnt);
+		return IRQ_NONE;
+	}
+
 	mac_control = &sp->mac_control;
 	config = &sp->config;
 




^ permalink raw reply

* [PATCH 2.6.24 5/5]S2io: Optimize isr fast path
From: Ramkrishna Vepa @ 2007-08-16  0:12 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Optimized interrupt routine fast path.

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Santosh Rastapur <santosh.rastapur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -Nurp patch4/drivers/net/s2io.c patch5/drivers/net/s2io.c
--- patch4/drivers/net/s2io.c	2007-08-15 08:42:14.000000000 -0700
+++ patch5/drivers/net/s2io.c	2007-08-15 08:42:51.000000000 -0700
@@ -84,7 +84,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.1"
+#define DRV_VERSION "2.0.26.2"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -4917,71 +4917,76 @@ static irqreturn_t s2io_isr(int irq, voi
 	 * 1. Rx of packet.
 	 * 2. Tx complete.
 	 * 3. Link down.
-	 * 4. Error in any functional blocks of the NIC.
 	 */
 	reason = readq(&bar0->general_int_status);
 
-	if (!reason) {
-		/* The interrupt was not raised by us. */
+	if (unlikely(reason == S2IO_MINUS_ONE) ) {
+		/* Nothing much can be done. Get out */
 		atomic_dec(&sp->isr_cnt);
-		return IRQ_NONE;
-	}
-	else if (unlikely(reason == S2IO_MINUS_ONE) ) {
-		/* Disable device and get out */
-		atomic_dec(&sp->isr_cnt);
-		return IRQ_NONE;
+		return IRQ_HANDLED;
 	}
 
-	if (napi) {
-		if (reason & GEN_INTR_RXTRAFFIC) {
-			if ( likely ( netif_rx_schedule_prep(dev)) ) {
-				__netif_rx_schedule(dev);
-				writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
+	if (reason & (GEN_INTR_RXTRAFFIC |
+		GEN_INTR_TXTRAFFIC | GEN_INTR_TXPIC))
+	{
+		writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
+
+		if (config->napi) {
+			if (reason & GEN_INTR_RXTRAFFIC) {
+				if ( likely (netif_rx_schedule_prep(dev)) ) {
+					__netif_rx_schedule(dev);
+					writeq(S2IO_MINUS_ONE,
+						&bar0->rx_traffic_mask);
+				} else
+					writeq(S2IO_MINUS_ONE,
+						&bar0->rx_traffic_int);
 			}
-			else
+		} else {
+			/*
+			 * rx_traffic_int reg is an R1 register, writing all 1's
+			 * will ensure that the actual interrupt causing bit
+			 * get's cleared and hence a read can be avoided.
+			 */
+			if (reason & GEN_INTR_RXTRAFFIC)
 				writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+
+			for (i = 0; i < config->rx_ring_num; i++)
+				rx_intr_handler(&mac_control->rings[i]);
 		}
-	} else {
+
 		/*
-		 * Rx handler is called by default, without checking for the
-		 * cause of interrupt.
-		 * rx_traffic_int reg is an R1 register, writing all 1's
+		 * tx_traffic_int reg is an R1 register, writing all 1's
 		 * will ensure that the actual interrupt causing bit get's
 		 * cleared and hence a read can be avoided.
 		 */
-		if (reason & GEN_INTR_RXTRAFFIC)
-			writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+		if (reason & GEN_INTR_TXTRAFFIC)
+			writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
 
-		for (i = 0; i < config->rx_ring_num; i++) {
-			rx_intr_handler(&mac_control->rings[i]);
-		}
-	}
+		for (i = 0; i < config->tx_fifo_num; i++)
+			tx_intr_handler(&mac_control->fifos[i]);
 
-	/*
-	 * tx_traffic_int reg is an R1 register, writing all 1's
-	 * will ensure that the actual interrupt causing bit get's
-	 * cleared and hence a read can be avoided.
-	 */
-	if (reason & GEN_INTR_TXTRAFFIC)
-		writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
+		if (reason & GEN_INTR_TXPIC)
+			s2io_txpic_intr_handle(sp);
 
-	for (i = 0; i < config->tx_fifo_num; i++)
-		tx_intr_handler(&mac_control->fifos[i]);
+		/*
+		 * Reallocate the buffers from the interrupt handler itself.
+		 */
+		if (!config->napi) {
+			for (i = 0; i < config->rx_ring_num; i++)
+				s2io_chk_rx_buffers(sp, i);
+		}
+		writeq(sp->general_int_mask, &bar0->general_int_mask);
+		readl(&bar0->general_int_status);
 
-	if (reason & GEN_INTR_TXPIC)
-		s2io_txpic_intr_handle(sp);
-	/*
-	 * If the Rx buffer count is below the panic threshold then
-	 * reallocate the buffers from the interrupt handler itself,
-	 * else schedule a tasklet to reallocate the buffers.
-	 */
-	if (!napi) {
-		for (i = 0; i < config->rx_ring_num; i++)
-			s2io_chk_rx_buffers(sp, i);
-	}
+		atomic_dec(&sp->isr_cnt);
+		return IRQ_HANDLED;
 
-	writeq(0, &bar0->general_int_mask);
-	readl(&bar0->general_int_status);
+	}
+	else if (!reason) {
+		/* The interrupt was not raised by us */
+		atomic_dec(&sp->isr_cnt);
+		return IRQ_NONE;
+	}
 
 	atomic_dec(&sp->isr_cnt);
 	return IRQ_HANDLED;
@@ -7109,6 +7114,14 @@ static void s2io_rem_isr(struct s2io_nic
 	struct net_device *dev = sp->dev;
 	struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
 
+	/* Waiting till all Interrupt handlers are complete */
+	do {
+		if (!atomic_read(&sp->isr_cnt))
+			break;
+		msleep(10);
+		cnt++;
+	} while(cnt < 5);
+
 	if (sp->config.intr_type == MSI_X) {
 		int i;
 		u16 msi_control;
@@ -7138,14 +7151,6 @@ static void s2io_rem_isr(struct s2io_nic
 	} else {
 		free_irq(sp->pdev->irq, dev);
 	}
-	/* Waiting till all Interrupt handlers are complete */
-	cnt = 0;
-	do {
-		msleep(10);
-		if (!atomic_read(&sp->isr_cnt))
-			break;
-		cnt++;
-	} while(cnt < 5);
 }
 
 static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
@@ -7676,19 +7681,12 @@ static int s2io_verify_parm(struct pci_d
 	if (*dev_intr_type != INTA)
 		napi = 0;
 
-#ifndef CONFIG_PCI_MSI
-	if (*dev_intr_type != INTA) {
-		DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
-			  "MSI/MSI-X. Defaulting to INTA\n");
-		*dev_intr_type = INTA;
-	}
-#else
 	if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) {
 		DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
 			  "Defaulting to INTA\n");
 		*dev_intr_type = INTA;
 	}
-#endif
+
 	if ((*dev_intr_type == MSI_X) &&
 			((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
 			(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
@@ -7846,6 +7844,8 @@ s2io_init_nic(struct pci_dev *pdev, cons
 	mac_control = &sp->mac_control;
 	config = &sp->config;
 
+	config->napi = napi;
+
 	/* Tx side parameters. */
 	config->tx_fifo_num = tx_fifo_num;
 	for (i = 0; i < MAX_TX_FIFOS; i++) {




^ permalink raw reply

* [PATCH 2.6.24 1/2]S2io: Change kmalloc+memset to k[zc]alloc
From: Ramkrishna Vepa @ 2007-08-16  0:13 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Changed kmalloc+memset to k[zc]alloc as per Mariusz's patch
  <m.kozlowski@tuxland.pl>

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -urpN org/drivers/net/s2io.c patch1/drivers/net/s2io.c
--- org/drivers/net/s2io.c	2007-08-09 17:28:19.000000000 +0530
+++ patch1/drivers/net/s2io.c	2007-08-10 11:53:46.000000000 +0530
@@ -556,7 +556,7 @@ static int init_shared_mem(struct s2io_n
 	for (i = 0; i < config->tx_fifo_num; i++) {
 		int fifo_len = config->tx_cfg[i].fifo_len;
 		int list_holder_size = fifo_len * sizeof(struct list_info_hold);
-		mac_control->fifos[i].list_info = kmalloc(list_holder_size,
+		mac_control->fifos[i].list_info = kzalloc(list_holder_size,
 							  GFP_KERNEL);
 		if (!mac_control->fifos[i].list_info) {
 			DBG_PRINT(INFO_DBG,
@@ -564,7 +564,6 @@ static int init_shared_mem(struct s2io_n
 			return -ENOMEM;
 		}
 		mem_allocated += list_holder_size;
-		memset(mac_control->fifos[i].list_info, 0, list_holder_size);
 	}
 	for (i = 0; i < config->tx_fifo_num; i++) {
 		int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
@@ -3883,9 +3882,9 @@ static int s2io_enable_msi_x(struct s2io
 	u16 msi_control; /* Temp variable */
 	int ret, i, j, msix_indx = 1;
 
-	nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
+	nic->entries = kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct msix_entry),
 			       GFP_KERNEL);
-	if (nic->entries == NULL) {
+	if (!nic->entries) {
 		DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \
 			__FUNCTION__);
 		nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
@@ -3893,12 +3892,11 @@ static int s2io_enable_msi_x(struct s2io
 	}
 	nic->mac_control.stats_info->sw_stat.mem_allocated 
 		+= (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
-	memset(nic->entries, 0,MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
 
 	nic->s2io_entries =
-		kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
+		kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct s2io_msix_entry),
 				   GFP_KERNEL);
-	if (nic->s2io_entries == NULL) {
+	if (!nic->s2io_entries) {
 		DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", 
 			__FUNCTION__);
 		nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
@@ -3909,8 +3907,6 @@ static int s2io_enable_msi_x(struct s2io
 	}
 	 nic->mac_control.stats_info->sw_stat.mem_allocated 
 		+= (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
-	memset(nic->s2io_entries, 0,
-	       MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
 
 	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
 		nic->entries[i].entry = i;




^ permalink raw reply

* [PATCH 2.6.24 2/2]S2io: Removed unused feature - bimodal interrupts
From: Ramkrishna Vepa @ 2007-08-16  0:13 UTC (permalink / raw)
  To: netdev; +Cc: jeff, support

- Removed bimodal interrupt support - unused feature

Signed-off-by: Sivakumar Subramani <sivakumar.subramani@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -urpN patch1/drivers/net/s2io.c patch2/drivers/net/s2io.c
--- patch1/drivers/net/s2io.c	2007-08-10 11:53:46.000000000 +0530
+++ patch2/drivers/net/s2io.c	2007-08-10 11:54:21.000000000 +0530
@@ -84,7 +84,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.3"
+#define DRV_VERSION "2.0.26.4"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -447,7 +447,6 @@ S2IO_PARM_INT(mc_pause_threshold_q4q7, 1
 S2IO_PARM_INT(shared_splits, 0);
 S2IO_PARM_INT(tmac_util_period, 5);
 S2IO_PARM_INT(rmac_util_period, 5);
-S2IO_PARM_INT(bimodal, 0);
 S2IO_PARM_INT(l3l4hdr_size, 128);
 /* Frequency of Rx desc syncs expressed as power of 2 */
 S2IO_PARM_INT(rxsync_frequency, 3);
@@ -1559,90 +1558,57 @@ static int init_nic(struct s2io_nic *nic
 		time++;
 	}
 
-	if (nic->config.bimodal) {
-		int k = 0;
-		for (k = 0; k < config->rx_ring_num; k++) {
-			val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
-			val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
-			writeq(val64, &bar0->tti_command_mem);
-
+	/* RTI Initialization */
+	if (nic->device_type == XFRAME_II_DEVICE) {
 		/*
-		 * Once the operation completes, the Strobe bit of the command
-		 * register will be reset. We poll for this particular condition
-		 * We wait for a maximum of 500ms for the operation to complete,
-		 * if it's not complete by then we return error.
-		*/
-			time = 0;
-			while (TRUE) {
-				val64 = readq(&bar0->tti_command_mem);
-				if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
-					break;
-				}
-				if (time > 10) {
-					DBG_PRINT(ERR_DBG,
-						"%s: TTI init Failed\n",
-					dev->name);
-					return -1;
-				}
-				time++;
-				msleep(50);
-			}
-		}
-	} else {
+		 * Programmed to generate Apprx 500 Intrs per
+		 * second
+		 */
+		int count = (nic->config.bus_speed * 125)/4;
+		val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
+	} else
+		val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
 
-		/* RTI Initialization */
-		if (nic->device_type == XFRAME_II_DEVICE) {
-			/*
-			 * Programmed to generate Apprx 500 Intrs per
-			 * second
-			 */
-			int count = (nic->config.bus_speed * 125)/4;
-			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
-		} else {
-			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
-		}
-		val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
-		    RTI_DATA1_MEM_RX_URNG_B(0x10) |
-		    RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
-
-		writeq(val64, &bar0->rti_data1_mem);
-
-		val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
-		    RTI_DATA2_MEM_RX_UFC_B(0x2) ;
-		if (nic->config.intr_type == MSI_X)
-		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
+	val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
+		RTI_DATA1_MEM_RX_URNG_B(0x10) |
+		RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
+
+	writeq(val64, &bar0->rti_data1_mem);
+
+	val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
+		RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+	if (nic->config.intr_type == MSI_X)
+		val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
 				RTI_DATA2_MEM_RX_UFC_D(0x40));
-		else
-		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
+	else
+		val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
 				RTI_DATA2_MEM_RX_UFC_D(0x80));
-		writeq(val64, &bar0->rti_data2_mem);
+	writeq(val64, &bar0->rti_data2_mem);
 
-		for (i = 0; i < config->rx_ring_num; i++) {
-			val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
-					| RTI_CMD_MEM_OFFSET(i);
-			writeq(val64, &bar0->rti_command_mem);
+	for (i = 0; i < config->rx_ring_num; i++) {
+		val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
+			| RTI_CMD_MEM_OFFSET(i);
+		writeq(val64, &bar0->rti_command_mem);
 
-			/*
-			 * Once the operation completes, the Strobe bit of the
-			 * command register will be reset. We poll for this
-			 * particular condition. We wait for a maximum of 500ms
-			 * for the operation to complete, if it's not complete
-			 * by then we return error.
-			 */
-			time = 0;
-			while (TRUE) {
-				val64 = readq(&bar0->rti_command_mem);
-				if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
-					break;
-				}
-				if (time > 10) {
-					DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
-						  dev->name);
-					return -1;
-				}
-				time++;
-				msleep(50);
+		/*
+		 * Once the operation completes, the Strobe bit of the
+		 * command register will be reset. We poll for this
+		 * particular condition. We wait for a maximum of 500ms
+		 * for the operation to complete, if it's not complete
+		 * by then we return error.
+		 */
+		time = 0;
+		while (TRUE) {
+			val64 = readq(&bar0->rti_command_mem);
+			if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD))
+				break;
+			if (time > 10) {
+				DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
+					  dev->name);
+				return -1;
 			}
+			time++;
+			msleep(50);
 		}
 	}
 
@@ -2358,8 +2324,6 @@ static int start_nic(struct s2io_nic *ni
 		       &bar0->prc_rxd0_n[i]);
 
 		val64 = readq(&bar0->prc_ctrl_n[i]);
-		if (nic->config.bimodal)
-			val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
 		if (nic->rxd_mode == RXD_MODE_1)
 			val64 |= PRC_CTRL_RC_ENABLED;
 		else
@@ -3924,27 +3888,14 @@ static int s2io_enable_msi_x(struct s2io
 	}
 	writeq(tx_mat, &bar0->tx_mat0_n[0]);
 
-	if (!nic->config.bimodal) {
-		rx_mat = readq(&bar0->rx_mat);
-		for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
-			rx_mat |= RX_MAT_SET(j, msix_indx);
-			nic->s2io_entries[msix_indx].arg 
-				= &nic->mac_control.rings[j];
-			nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
-			nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
-		}
-		writeq(rx_mat, &bar0->rx_mat);
-	} else {
-		tx_mat = readq(&bar0->tx_mat0_n[7]);
-		for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
-			tx_mat |= TX_MAT_SET(i, msix_indx);
-			nic->s2io_entries[msix_indx].arg 
-				= &nic->mac_control.rings[j];
-			nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
-			nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
-		}
-		writeq(tx_mat, &bar0->tx_mat0_n[7]);
+	rx_mat = readq(&bar0->rx_mat);
+	for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+		rx_mat |= RX_MAT_SET(j, msix_indx);
+		nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+		nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+		nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
 	}
+	writeq(rx_mat, &bar0->rx_mat);
 
 	nic->avail_msix_vectors = 0;
 	ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
@@ -8118,14 +8069,6 @@ s2io_init_nic(struct pci_dev *pdev, cons
 	/* Initialize device name */
 	sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
 
-	/* Initialize bimodal Interrupts */
-	sp->config.bimodal = bimodal;
-	if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) {
-		sp->config.bimodal = 0;
-		DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n",
-			dev->name);
-	}
-
 	/*
 	 * Make Link state as off at this point, when the Link change
 	 * interrupt comes the state will be automatically changed to
diff -urpN patch1/drivers/net/s2io.h patch2/drivers/net/s2io.h
--- patch1/drivers/net/s2io.h	2007-08-09 17:28:36.000000000 +0530
+++ patch2/drivers/net/s2io.h	2007-08-10 11:33:56.000000000 +0530
@@ -444,7 +444,6 @@ struct config_param {
 #define MAX_RX_BLOCKS_PER_RING  150
 
 	struct rx_ring_config rx_cfg[MAX_RX_RINGS];	/*Per-Rx Ring config */
-	u8 bimodal;		/*Flag for setting bimodal interrupts*/
 
 #define HEADER_ETHERNET_II_802_3_SIZE 14
 #define HEADER_802_2_SIZE              3




^ permalink raw reply

* Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
From: Paul E. McKenney @ 2007-08-15 22:42 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: horms, Stefan Richter, Satyam Sharma, Linux Kernel Mailing List,
	rpjday, netdev, ak, cfriesen, Heiko Carstens, jesper.juhl,
	linux-arch, Andrew Morton, zlynx, clameter, schwidefsky,
	Chris Snook, Herbert Xu, davem, Linus Torvalds, wensong, wjiang
In-Reply-To: <96f3fa3929d873263891fefadb222431@kernel.crashing.org>

On Wed, Aug 15, 2007 at 10:52:53PM +0200, Segher Boessenkool wrote:
> >>I think this was just terminology confusion here again. Isn't "any 
> >>code
> >>that it cannot currently see" the same as "another compilation unit",
> >>and wouldn't the "compilation unit" itself expand if we ask gcc to
> >>compile more than one unit at once? Or is there some more specific
> >>"definition" for "compilation unit" (in gcc lingo, possibly?)
> >
> >This is indeed my understanding -- "compilation unit" is whatever the
> >compiler looks at in one go.  I have heard the word "module" used for
> >the minimal compilation unit covering a single .c file and everything
> >that it #includes, but there might be a better name for this.
> 
> Yes, that's what's called "compilation unit" :-)
> 
> [/me double checks]
> 
> Erm, the C standard actually calls it "translation unit".
> 
> To be exact, to avoid any more confusion:
> 
> 5.1.1.1/1:
> A C program need not all be translated at the same time. The
> text of the program is kept in units called source files, (or
> preprocessing files) in this International Standard. A source
> file together with all the headers and source files included
> via the preprocessing directive #include is known as a
> preprocessing translation unit. After preprocessing, a
> preprocessing translation unit is called a translation unit.

I am OK with "translation" and "compilation" being near-synonyms.  ;-)

						Thanx, Paul

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox