* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 10:37 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1B5BC.5020103@monstr.eu>
Le mercredi 21 décembre 2011 à 11:32 +0100, Michal Simek a écrit :
> Eric Dumazet wrote:
> > Le mercredi 21 décembre 2011 à 11:28 +0100, Eric Dumazet a écrit :
> >> Le mercredi 21 décembre 2011 à 11:11 +0100, Michal Simek a écrit :
> >>> Hi Eric and David,
> >>>
> >>> I have found one problem with ll_temac driver and
> >>> this commit: net: more accurate skb truesize
> >>> sha1: 87fb4b7b533073eeeaed0b6bf7c2328995f6c075
> >>>
> >>> The problem is only with icmp packets from the target. It is sent and driver receive it
> >>> but it is not proceed to the application.
> >>>
> >>> The problem I see is that kmalloc_node_track_caller allocate
> >>> specific size and then this size is changed by SKB_WITH_OVERHEAD(ksize(data)).
> >>> The problem is with netdev_alloc_skb_ip_align which calls __alloc_skb function.
> >>>
> >>> Currently driver uses setting for jumbo frames (9k). When I change it to use mtu (1,5k) then
> >>> everything is ok.
> >>>
> >>> Can you give me some hints what can be wrong?
> >>>
> >> Is it with SLUB, SLAB or SLOB allocator ?
> >>
> >>
> >
> > (I am referring to commit bc417e30f8d
> > (net: Add back alignment for size for __alloc_skb)
>
> I have seen that commit. Using the latest&greatest version with this patch.
>
So after these changes, struct skb_shared_info is located to the very
end of allocated memory.
Maybe there is a problem with MTU=9000, since assuming PAGE_SIZE=4096 on
your machine (is it ?), we have a 16384 bytes block of memory, and
~16000 available in skb head, instead of ~9000
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Michal Simek @ 2011-12-21 10:41 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324463838.2728.24.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 11:32 +0100, Michal Simek a écrit :
>> Eric Dumazet wrote:
>>> Le mercredi 21 décembre 2011 à 11:28 +0100, Eric Dumazet a écrit :
>>>> Le mercredi 21 décembre 2011 à 11:11 +0100, Michal Simek a écrit :
>>>>> Hi Eric and David,
>>>>>
>>>>> I have found one problem with ll_temac driver and
>>>>> this commit: net: more accurate skb truesize
>>>>> sha1: 87fb4b7b533073eeeaed0b6bf7c2328995f6c075
>>>>>
>>>>> The problem is only with icmp packets from the target. It is sent and driver receive it
>>>>> but it is not proceed to the application.
>>>>>
>>>>> The problem I see is that kmalloc_node_track_caller allocate
>>>>> specific size and then this size is changed by SKB_WITH_OVERHEAD(ksize(data)).
>>>>> The problem is with netdev_alloc_skb_ip_align which calls __alloc_skb function.
>>>>>
>>>>> Currently driver uses setting for jumbo frames (9k). When I change it to use mtu (1,5k) then
>>>>> everything is ok.
>>>>>
>>>>> Can you give me some hints what can be wrong?
>>>>>
>>>> Is it with SLUB, SLAB or SLOB allocator ?
>>>>
>>>>
>>> (I am referring to commit bc417e30f8d
>>> (net: Add back alignment for size for __alloc_skb)
>> I have seen that commit. Using the latest&greatest version with this patch.
>>
>
> So after these changes, struct skb_shared_info is located to the very
> end of allocated memory.
>
> Maybe there is a problem with MTU=9000, since assuming PAGE_SIZE=4096 on
> your machine (is it ?), we have a 16384 bytes block of memory, and
> ~16000 available in skb head, instead of ~9000
yes, page size is 4k.
Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
overhead is 0x3f40(16192)
kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
skb->head c7870000
skb->data c7870000
skb->tail c7870000
skb->truesize 000040c0
skb->end c7873f40
Michal
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 10:45 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1B7E4.4010602@monstr.eu>
Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
> yes, page size is 4k.
>
> Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
> overhead is 0x3f40(16192)
>
> kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
> skb->head c7870000
> skb->data c7870000
> skb->tail c7870000
> skb->truesize 000040c0
> skb->end c7873f40
>
So basically truesize is bigger than previous kernel, and you hit a
socket limit. (RCVBUF ?)
truesize is more correct, so we uncover prior bugs.
We should allow at least one packet, regardless of its size :(
^ permalink raw reply
* Re: linux-next: manual merge of the wireless-next tree with the tree
From: Arend van Spriel @ 2011-12-21 10:47 UTC (permalink / raw)
To: Stephen Rothwell
Cc: John W. Linville, linux-next@vger.kernel.org,
linux-kernel@vger.kernel.org, Rusty Russell, David Miller,
netdev@vger.kernel.org, Franky (Zhenhui) Lin
In-Reply-To: <20111221124931.992e4e4265f2c3cd1d2e75b4@canb.auug.org.au>
On 12/21/2011 02:49 AM, Stephen Rothwell wrote:
> Hi John,
>
> Today's linux-next merge of the wireless-next tree got a conflict in
> drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c between commit
> 3db1cd5c05f3 ("net: fix assignment of 0/1 to bool variables") from the
> tree and commit 3fb1d8d2dad3 ("brcm80211: fmac: move driver up status to
> struct brcmf_bus") from the wireless-next tree.
>
> I fixed it up (see below) and can carry the fix as necessary.
>
Thanks, Stephen
I noticed Rusty's patch and the use of 0/1 for bool in our tree. Was
going to fix that, but this fix looks fine.
Gr. AvS
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Michal Simek @ 2011-12-21 10:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324464308.2728.26.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
>
>> yes, page size is 4k.
>>
>> Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
>> overhead is 0x3f40(16192)
>>
>> kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
>> skb->head c7870000
>> skb->data c7870000
>> skb->tail c7870000
>> skb->truesize 000040c0
>> skb->end c7873f40
>>
>
> So basically truesize is bigger than previous kernel, and you hit a
> socket limit. (RCVBUF ?)
Where is that limit setup?
Michal
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 11:03 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324464308.2728.26.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Le mercredi 21 décembre 2011 à 11:45 +0100, Eric Dumazet a écrit :
> Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
>
> > yes, page size is 4k.
> >
> > Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
> > overhead is 0x3f40(16192)
> >
> > kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
> > skb->head c7870000
> > skb->data c7870000
> > skb->tail c7870000
> > skb->truesize 000040c0
> > skb->end c7873f40
> >
>
> So basically truesize is bigger than previous kernel, and you hit a
> socket limit. (RCVBUF ?)
>
> truesize is more correct, so we uncover prior bugs.
>
> We should allow at least one packet, regardless of its size :(
>
>
I would try the following patch :
diff --git a/include/net/sock.h b/include/net/sock.h
index bf6b9fd..21bb3b5 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -662,12 +662,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
/*
* Take into account size of receive queue and backlog queue
+ * Do not take into account this skb truesize,
+ * to allow even a single big packet to come.
*/
static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb)
{
unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);
- return qsize + skb->truesize > sk->sk_rcvbuf;
+ return qsize > sk->sk_rcvbuf;
}
/* The per-socket spinlock must be held here. */
^ permalink raw reply related
* Re: [PATCH 0/4] skb paged fragment destructors
From: Ian Campbell @ 2011-12-21 11:03 UTC (permalink / raw)
To: David Miller
Cc: eric.dumazet@gmail.com, jesse.brandeburg@intel.com,
netdev@vger.kernel.org
In-Reply-To: <20111209.133407.2156473837364120429.davem@davemloft.net>
On Fri, 2011-12-09 at 18:34 +0000, David Miller wrote:
> From: Ian Campbell <Ian.Campbell@citrix.com>
> Date: Fri, 9 Dec 2011 13:47:07 +0000
>
> > If we had a concept like MAX_SKB_PAGES then it would perhaps make
> > sense to have + 2 there, but AFAICT drivers etc are already
> > accounting for this appropriately by adding a further + 2 (or
> > sometimes + 1) to MAX_SKB_FRAGS.
>
> Any kind of code like this, including the "+ 2" in the skbuff header,
> should be coded to use some kind of macro so we can track this
> dependency instead of stumbling onto it and accidently breaking lots
> of stuff if we want to change this "2" value.
Agreed.
Part of the problem is that no one seems to have any idea what this
particular + 2 means. My best hypothesis is that it accounts for the
pages used by the linear area (which potentially crosses a page
boundary).
On that basis I propose to do the following + a sweep of the tree to
determine who means which. There's quite a lot of MAX_SKB_FRAGS in the
tree but based on quick inspection many are related specifically to the
bounds of the frags list and so don't need to change.
/* To allow 64K frame to be packed as single skb without frag_list. Since
* GRO uses frags we allocate at least 16 regardless of page size.
*/
#if (65536/PAGE_SIZE) < 16
#define MAX_SKB_FRAGS 16UL
#else
#define MAX_SKB_FRAGS (65536/PAGE_SIZE)
#endif
/* The linear area can cross a page boundary */
#define MAX_SKB_HEAD_PAGES 2UL
#define MAX_SKB_PAGES (MAX_SKB_FRAGS + MAX_SKB_HEAD_PAGES)
This means that MAX_SKB_FRAGS will shrink by 2. The new symbol
MAX_SKB_PAGES will have the old value of MAX_SKB_FRAGS.
I'm also considering getting rid of the #if since I don't think we
support pages < 4K on any arch, do we?
To aid sequencing the transition it might be best to go with
MAX_SKB_FRAGS (16 + 2) and MAX_SKB_HEADER_PAGES (0) first, then convert
everyone to use the one they really meant and finally move the 2 from
SKB_FRAGS to SKB_HEADER_PAGES. I need to think about that.
Some drivers currently use MAX_SKB_FRAGS + 1 which I think is accounting
for the linear area in cases where the hardware cannot receive one cross
a page boundary. I'm considering defining MIN_SKB_HEAD_PAGES to use in
these circumstances.
Ian.
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 11:05 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1BAE1.7020409@monstr.eu>
Le mercredi 21 décembre 2011 à 11:54 +0100, Michal Simek a écrit :
> Eric Dumazet wrote:
> > Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
> >
> >> yes, page size is 4k.
> >>
> >> Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
> >> overhead is 0x3f40(16192)
> >>
> >> kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
> >> skb->head c7870000
> >> skb->data c7870000
> >> skb->tail c7870000
> >> skb->truesize 000040c0
> >> skb->end c7873f40
> >>
> >
> > So basically truesize is bigger than previous kernel, and you hit a
> > socket limit. (RCVBUF ?)
>
> Where is that limit setup?
>
Might be in the application itself.
setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &limit, sizeof(limit));
kernel currently apply a factor of two to take into account skb
overhead. This might be not enough with jumbo frames.
^ permalink raw reply
* Re: [PATCH 0/4] skb paged fragment destructors
From: Eric Dumazet @ 2011-12-21 11:08 UTC (permalink / raw)
To: Ian Campbell
Cc: David Miller, jesse.brandeburg@intel.com, netdev@vger.kernel.org
In-Reply-To: <1324465434.7877.11.camel@zakaz.uk.xensource.com>
Le mercredi 21 décembre 2011 à 11:03 +0000, Ian Campbell a écrit :
> On Fri, 2011-12-09 at 18:34 +0000, David Miller wrote:
> > From: Ian Campbell <Ian.Campbell@citrix.com>
> > Date: Fri, 9 Dec 2011 13:47:07 +0000
> >
> > > If we had a concept like MAX_SKB_PAGES then it would perhaps make
> > > sense to have + 2 there, but AFAICT drivers etc are already
> > > accounting for this appropriately by adding a further + 2 (or
> > > sometimes + 1) to MAX_SKB_FRAGS.
> >
> > Any kind of code like this, including the "+ 2" in the skbuff header,
> > should be coded to use some kind of macro so we can track this
> > dependency instead of stumbling onto it and accidently breaking lots
> > of stuff if we want to change this "2" value.
>
> Agreed.
>
> Part of the problem is that no one seems to have any idea what this
> particular + 2 means. My best hypothesis is that it accounts for the
> pages used by the linear area (which potentially crosses a page
> boundary).
I dont understand the point.
linear data is allocated with kmalloc(), so technically speaking its
located in a single page, but page order can be 0, 1, 2, 3, ...
MAX_ORDER.
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Michal Simek @ 2011-12-21 11:10 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324465386.2728.29.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 11:45 +0100, Eric Dumazet a écrit :
>> Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
>>
>>> yes, page size is 4k.
>>>
>>> Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
>>> overhead is 0x3f40(16192)
>>>
>>> kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
>>> skb->head c7870000
>>> skb->data c7870000
>>> skb->tail c7870000
>>> skb->truesize 000040c0
>>> skb->end c7873f40
>>>
>> So basically truesize is bigger than previous kernel, and you hit a
>> socket limit. (RCVBUF ?)
>>
>> truesize is more correct, so we uncover prior bugs.
>>
>> We should allow at least one packet, regardless of its size :(
>>
>>
>
> I would try the following patch :
>
> diff --git a/include/net/sock.h b/include/net/sock.h
> index bf6b9fd..21bb3b5 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -662,12 +662,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
>
> /*
> * Take into account size of receive queue and backlog queue
> + * Do not take into account this skb truesize,
> + * to allow even a single big packet to come.
> */
> static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb)
> {
> unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);
>
> - return qsize + skb->truesize > sk->sk_rcvbuf;
> + return qsize > sk->sk_rcvbuf;
> }
>
> /* The per-socket spinlock must be held here. */
>
It doesn't fix the problem. Do you want to add some printk to code?
Michal
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 11:13 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1BEA4.7080005@monstr.eu>
Le mercredi 21 décembre 2011 à 12:10 +0100, Michal Simek a écrit :
> Eric Dumazet wrote:
> > Le mercredi 21 décembre 2011 à 11:45 +0100, Eric Dumazet a écrit :
> >> Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
> >>
> >>> yes, page size is 4k.
> >>>
> >>> Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
> >>> overhead is 0x3f40(16192)
> >>>
> >>> kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
> >>> skb->head c7870000
> >>> skb->data c7870000
> >>> skb->tail c7870000
> >>> skb->truesize 000040c0
> >>> skb->end c7873f40
> >>>
> >> So basically truesize is bigger than previous kernel, and you hit a
> >> socket limit. (RCVBUF ?)
> >>
> >> truesize is more correct, so we uncover prior bugs.
> >>
> >> We should allow at least one packet, regardless of its size :(
> >>
> >>
> >
> > I would try the following patch :
> >
> > diff --git a/include/net/sock.h b/include/net/sock.h
> > index bf6b9fd..21bb3b5 100644
> > --- a/include/net/sock.h
> > +++ b/include/net/sock.h
> > @@ -662,12 +662,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
> >
> > /*
> > * Take into account size of receive queue and backlog queue
> > + * Do not take into account this skb truesize,
> > + * to allow even a single big packet to come.
> > */
> > static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb)
> > {
> > unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);
> >
> > - return qsize + skb->truesize > sk->sk_rcvbuf;
> > + return qsize > sk->sk_rcvbuf;
> > }
> >
> > /* The per-socket spinlock must be held here. */
> >
>
> It doesn't fix the problem. Do you want to add some printk to code?
>
> Michal
>
>
>
try to change SOCK_MIN_RCVBUF
include/net/sock.h
#define SOCK_MIN_RCVBUF (2048 + sizeof(struct sk_buff))
->
#define SOCK_MIN_RCVBUF (16384 + sizeof(struct sk_buff))
^ permalink raw reply
* Re: [PATCH 0/4] skb paged fragment destructors
From: Ian Campbell @ 2011-12-21 11:18 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, jesse.brandeburg@intel.com, netdev@vger.kernel.org
In-Reply-To: <1324465724.2728.34.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On Wed, 2011-12-21 at 11:08 +0000, Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 11:03 +0000, Ian Campbell a écrit :
> > On Fri, 2011-12-09 at 18:34 +0000, David Miller wrote:
> > > From: Ian Campbell <Ian.Campbell@citrix.com>
> > > Date: Fri, 9 Dec 2011 13:47:07 +0000
> > >
> > > > If we had a concept like MAX_SKB_PAGES then it would perhaps make
> > > > sense to have + 2 there, but AFAICT drivers etc are already
> > > > accounting for this appropriately by adding a further + 2 (or
> > > > sometimes + 1) to MAX_SKB_FRAGS.
> > >
> > > Any kind of code like this, including the "+ 2" in the skbuff header,
> > > should be coded to use some kind of macro so we can track this
> > > dependency instead of stumbling onto it and accidently breaking lots
> > > of stuff if we want to change this "2" value.
> >
> > Agreed.
> >
> > Part of the problem is that no one seems to have any idea what this
> > particular + 2 means. My best hypothesis is that it accounts for the
> > pages used by the linear area (which potentially crosses a page
> > boundary).
>
> I dont understand the point.
I did say hypothesis ;-) Do you know what that + 2 is actually all
about?
If no one knows what it is for maybe we should just remove it directly
instead of what I proposed?
> linear data is allocated with kmalloc(), so technically speaking its
> located in a single page, but page order can be 0, 1, 2, 3, ...
> MAX_ORDER.
I think I must misunderstand the terminology.
An order 1 allocation is in multiples of PAGE_SIZE, isn't it, even
though they happen to be contiguous?
Or are you considering the possibility of kmalloc returning a super page
of some description? Isn't that to some extent transparent to the caller
who (assuming PAGE_SIZE 4096) doesn't know if kmalloc(16384) returned
4*4096 contiguous pages or 1*16384 page?
Anyway I take your underlying point that 2*PAGE_SIZE is no kind of limit
on the size of the linear region.
Ian.
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Michal Simek @ 2011-12-21 11:50 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324466023.2728.36.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 12:10 +0100, Michal Simek a écrit :
>> Eric Dumazet wrote:
>>> Le mercredi 21 décembre 2011 à 11:45 +0100, Eric Dumazet a écrit :
>>>> Le mercredi 21 décembre 2011 à 11:41 +0100, Michal Simek a écrit :
>>>>
>>>>> yes, page size is 4k.
>>>>>
>>>>> Here is the log for allocation - origin size for MTU 9000 is 0x2420(9248) and size after
>>>>> overhead is 0x3f40(16192)
>>>>>
>>>>> kmalloc_node_track_caller size 00002420, SKB_WITH_OVERHEAD(ksize(data)) 00003f40
>>>>> skb->head c7870000
>>>>> skb->data c7870000
>>>>> skb->tail c7870000
>>>>> skb->truesize 000040c0
>>>>> skb->end c7873f40
>>>>>
>>>> So basically truesize is bigger than previous kernel, and you hit a
>>>> socket limit. (RCVBUF ?)
>>>>
>>>> truesize is more correct, so we uncover prior bugs.
>>>>
>>>> We should allow at least one packet, regardless of its size :(
>>>>
>>>>
>>> I would try the following patch :
>>>
>>> diff --git a/include/net/sock.h b/include/net/sock.h
>>> index bf6b9fd..21bb3b5 100644
>>> --- a/include/net/sock.h
>>> +++ b/include/net/sock.h
>>> @@ -662,12 +662,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
>>>
>>> /*
>>> * Take into account size of receive queue and backlog queue
>>> + * Do not take into account this skb truesize,
>>> + * to allow even a single big packet to come.
>>> */
>>> static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb)
>>> {
>>> unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);
>>>
>>> - return qsize + skb->truesize > sk->sk_rcvbuf;
>>> + return qsize > sk->sk_rcvbuf;
>>> }
>>>
>>> /* The per-socket spinlock must be held here. */
>>>
>> It doesn't fix the problem. Do you want to add some printk to code?
>>
>> Michal
>>
>>
>>
>
> try to change SOCK_MIN_RCVBUF
>
> include/net/sock.h
>
> #define SOCK_MIN_RCVBUF (2048 + sizeof(struct sk_buff))
>
> ->
>
> #define SOCK_MIN_RCVBUF (16384 + sizeof(struct sk_buff))
>
Doesn't work. :-(
Michal
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply
* linux-next: manual merge of the wireless-next tree with the net-next tree
From: Stephen Rothwell @ 2011-12-21 11:59 UTC (permalink / raw)
To: John W. Linville
Cc: linux-next, linux-kernel, Rusty Russell, David Miller, netdev,
francesco.gringoli
[-- Attachment #1: Type: text/plain, Size: 2218 bytes --]
[Resending to get through vger's address checks - sorry for duplicate]
Hi John,
Today's linux-next merge of the wireless-next tree got a conflict in
drivers/net/wireless/b43/dma.c between commit 3db1cd5c05f3 ("net: fix
assignment of 0/1 to bool variables") from the net-next tree and commit
bad691946966 ("b43: avoid packet losses in the dma worker code") from the
wireless-next tree.
Just context changes. I fixed it up (see below) and can carry the fix as
necessary.
The newly created tx_queue_stopped array element assignments should be
changed form 0/1 to false/true as well (here and in main.c).
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --cc drivers/net/wireless/b43/dma.c
index af23968,56d37dc..0000000
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@@ -1465,8 -1465,10 +1465,10 @@@ int b43_dma_tx(struct b43_wldev *dev, s
if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
- ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+ unsigned int skb_mapping = skb_get_queue_mapping(skb);
+ ieee80211_stop_queue(dev->wl->hw, skb_mapping);
+ dev->wl->tx_queue_stopped[skb_mapping] = 1;
- ring->stopped = 1;
+ ring->stopped = true;
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
}
@@@ -1584,8 -1586,15 +1586,15 @@@ void b43_dma_handle_txstatus(struct b43
}
if (ring->stopped) {
B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
- ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
- ring->stopped = 0;
+ ring->stopped = false;
+ }
+
+ if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
+ dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+ } else {
+ /* If the driver queue is running wake the corresponding
+ * mac80211 queue. */
+ ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
}
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH 0/4] skb paged fragment destructors
From: Eric Dumazet @ 2011-12-21 12:30 UTC (permalink / raw)
To: Ian Campbell
Cc: David Miller, jesse.brandeburg@intel.com, netdev@vger.kernel.org
In-Reply-To: <1324466290.7877.22.camel@zakaz.uk.xensource.com>
Le mercredi 21 décembre 2011 à 11:18 +0000, Ian Campbell a écrit :
>
> An order 1 allocation is in multiples of PAGE_SIZE, isn't it, even
> though they happen to be contiguous?
Really an order-1 allocation allocates one page, a compound one.
>
> Or are you considering the possibility of kmalloc returning a super page
> of some description? Isn't that to some extent transparent to the caller
> who (assuming PAGE_SIZE 4096) doesn't know if kmalloc(16384) returned
> 4*4096 contiguous pages or 1*16384 page?
>
Its a part of a _single_ page, or the total of it.
Its mandatory, or else many drivers would break their DMA handling.
> Anyway I take your underlying point that 2*PAGE_SIZE is no kind of limit
> on the size of the linear region.
>
Sure, since net/unix/af_unix.c can happily allocate huge linear skbs, if
memory is not too fragmented of course...
(The stream unix socket limit their skbs to SKB_MAX_ALLOC (up to 4
pages), but datagram ones have no limit)
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 12:39 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1C80B.4060701@monstr.eu>
Le mercredi 21 décembre 2011 à 12:50 +0100, Michal Simek a écrit :
> > #define SOCK_MIN_RCVBUF (16384 + sizeof(struct sk_buff))
> >
>
> Doesn't work. :-(
>
Sorry, I have no idea where packet is dropped, I dont know your
application.
You might send "netstat -s" output if you cant find it ...
You spoke of ICMP message, I cant find a limit in this area ?
^ permalink raw reply
* [PATCH] irda: use msecs_to_jiffies() rather than manual calculation
From: Xi Wang @ 2011-12-21 12:57 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: netdev, David S. Miller, Xi Wang
Also use mod_timer() instead of direct assignment to "expires".
Signed-off-by: Xi Wang <xi.wang@gmail.com>
---
net/irda/af_irda.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index c24f25a..bb14c34 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2558,8 +2558,8 @@ bed:
self->errno = 0;
setup_timer(&self->watchdog, irda_discovery_timeout,
(unsigned long)self);
- self->watchdog.expires = jiffies + (val * HZ/1000);
- add_timer(&(self->watchdog));
+ mod_timer(&self->watchdog,
+ jiffies + msecs_to_jiffies(val));
/* Wait for IR-LMP to call us back */
__wait_event_interruptible(self->query_wait,
--
1.7.5.4
^ permalink raw reply related
* Warning! Your mailbox is almost full.
From: Ceejay Desfosses @ 2011-12-21 12:48 UTC (permalink / raw)
Your mailbox has exceeded the storage limit is 1 GB, which is
defined by the administrator, are running at 99.8 gigabytes, you can not
send or receive new messages until you re-validate your mailbox.
To renew the mailbox,
click link below:
http://www.scd-lunjina.org/form/use/ask/form1.html
Thank you!
Webmail system administrator!
WARNING! Protect your privacy. Logout when you are done and completely
exit your browser.
Other Campus WebMail Services
^ permalink raw reply
* Re: ICMP packets - ll_temac with Microblaze
From: Michal Simek @ 2011-12-21 13:28 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324471194.2728.44.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 12:50 +0100, Michal Simek a écrit :
>
>>> #define SOCK_MIN_RCVBUF (16384 + sizeof(struct sk_buff))
>>>
>> Doesn't work. :-(
>>
>
> Sorry, I have no idea where packet is dropped, I dont know your
> application.
Application is simple ping from Busybox - nothing special.
> You might send "netstat -s" output if you cant find it ...
~ # ./netstat -s
Ip:
36 total packets received
2 with invalid addresses
0 forwarded
0 incoming packets discarded
34 incoming packets delivered
34 requests sent out
Icmp:
34 ICMP messages received
0 input ICMP message failed.
ICMP input histogram:
echo replies: 34
34 ICMP messages sent
0 ICMP messages failed
ICMP output histogram:
echo request: 34
IcmpMsg:
InType0: 34
OutType8: 34
Tcp:
0 active connections openings
0 passive connection openings
0 failed connection attempts
0 connection resets received
0 connections established
0 segments received
0 segments send out
0 segments retransmited
0 bad segments received.
0 resets sent
Udp:
0 packets received
0 packets to unknown port received.
0 packet receive errors
0 packets sent
RcvbufErrors: 0
SndbufErrors: 0
UdpLite:
InDatagrams: 0
NoPorts: 0
InErrors: 0
OutDatagrams: 0
RcvbufErrors: 0
SndbufErrors: 0
TcpExt:
ArpFilter: 0
0 packets header predicted
TCPPureAcks: 0
TCPHPAcks: 0
TCPRenoRecovery: 0
TCPSackRecovery: 0
TCPSACKReneging: 0
TCPFACKReorder: 0
TCPSACKReorder: 0
TCPRenoReorder: 0
TCPTSReorder: 0
TCPFullUndo: 0
TCPPartialUndo: 0
TCPDSACKUndo: 0
TCPLossUndo: 0
TCPLoss: 0
TCPLostRetransmit: 0
TCPRenoFailures: 0
TCPSackFailures: 0
TCPLossFailures: 0
TCPFastRetrans: 0
TCPForwardRetrans: 0
TCPSlowStartRetrans: 0
TCPTimeouts: 0
TCPRenoRecoveryFail: 0
TCPSackRecoveryFail: 0
TCPSchedulerFailed: 0
TCPRcvCollapsed: 0
TCPDSACKOldSent: 0
TCPDSACKOfoSent: 0
TCPDSACKRecv: 0
TCPDSACKOfoRecv: 0
TCPAbortOnSyn: 0
TCPAbortOnData: 0
TCPAbortOnClose: 0
TCPAbortOnMemory: 0
TCPAbortOnTimeout: 0
TCPAbortOnLinger: 0
TCPAbortFailed: 0
TCPMemoryPressures: 0
TCPSACKDiscard: 0
TCPDSACKIgnoredOld: 0
TCPDSACKIgnoredNoUndo: 0
TCPSpuriousRTOs: 0
TCPMD5NotFound: 0
TCPMD5Unexpected: 0
TCPSackShifted: 0
TCPSackMerged: 0
TCPSackShiftFallback: 0
TCPBacklogDrop: 0
TCPMinTTLDrop: 0
TCPDeferAcceptDrop: 0
IPReversePathFilter: 0
TCPTimeWaitOverflow: 0
TCPReqQFullDoCookies: 0
TCPReqQFullDrop: 0
IpExt:
InNoRoutes: 0
InTruncatedPkts: 0
InMcastPkts: 0
OutMcastPkts: 0
InBcastPkts: 0
OutBcastPkts: 0
InOctets: 4008
OutOctets: 2856
InMcastOctets: 0
OutMcastOctets: 0
InBcastOctets: 0
OutBcastOctets: 0
> You spoke of ICMP message, I cant find a limit in this area ?
ok. Can you provide me any background why size should be setup by
size = SKB_WITH_OVERHEAD(ksize(data));
and not to use size which is passed to kmalloc in __alloc_skb.
In past I have seen some issues because of caches but this is not that
case because on QEMU (where cache is not modeled) everything works the same as on HW.
Below is the log what I see.
Thanks,
Michal
~ # ping -c 5 192.168.0.101
PING 192.168.0.101 (192.168.0.101): 56 data bytes
--- 192.168.0.101 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss
~ # mount -t nfs -o nolock -o tcp 192.168.0.101:/tftpboot/nfs /mnt
~ # ls /mnt/ | head
0001-sd.patch
0001-syscalls-getdtablesize01-fix-for-missing-etc-hosts.patch
1
1-xils
2
arp
arp-mb
busybox
core
exec
~ # umount /mnt/
~ # ./netstat -s
Ip:
36 total packets received
2 with invalid addresses
0 forwarded
0 incoming packets discarded
34 incoming packets delivered
43 requests sent out
Icmp:
5 ICMP messages received
0 input ICMP message failed.
ICMP input histogram:
echo replies: 5
5 ICMP messages sent
0 ICMP messages failed
ICMP output histogram:
echo request: 5
IcmpMsg:
InType0: 5
OutType8: 5
Tcp:
4 active connections openings
0 passive connection openings
0 failed connection attempts
0 connection resets received
0 connections established
29 segments received
38 segments send out
0 segments retransmited
0 bad segments received.
0 resets sent
Udp:
0 packets received
0 packets to unknown port received.
0 packet receive errors
0 packets sent
RcvbufErrors: 0
SndbufErrors: 0
UdpLite:
InDatagrams: 0
NoPorts: 0
InErrors: 0
OutDatagrams: 0
RcvbufErrors: 0
SndbufErrors: 0
TcpExt:
ArpFilter: 0
1 delayed acks sent
10 packets header predicted
TCPPureAcks: 4
TCPHPAcks: 6
TCPRenoRecovery: 0
TCPSackRecovery: 0
TCPSACKReneging: 0
TCPFACKReorder: 0
TCPSACKReorder: 0
TCPRenoReorder: 0
TCPTSReorder: 0
TCPFullUndo: 0
TCPPartialUndo: 0
TCPDSACKUndo: 0
TCPLossUndo: 0
TCPLoss: 0
TCPLostRetransmit: 0
TCPRenoFailures: 0
TCPSackFailures: 0
TCPLossFailures: 0
TCPFastRetrans: 0
TCPForwardRetrans: 0
TCPSlowStartRetrans: 0
TCPTimeouts: 0
TCPRenoRecoveryFail: 0
TCPSackRecoveryFail: 0
TCPSchedulerFailed: 0
TCPRcvCollapsed: 0
TCPDSACKOldSent: 0
TCPDSACKOfoSent: 0
TCPDSACKRecv: 0
TCPDSACKOfoRecv: 0
TCPAbortOnSyn: 0
TCPAbortOnData: 0
TCPAbortOnClose: 0
TCPAbortOnMemory: 0
TCPAbortOnTimeout: 0
TCPAbortOnLinger: 0
TCPAbortFailed: 0
TCPMemoryPressures: 0
TCPSACKDiscard: 0
TCPDSACKIgnoredOld: 0
TCPDSACKIgnoredNoUndo: 0
TCPSpuriousRTOs: 0
TCPMD5NotFound: 0
TCPMD5Unexpected: 0
TCPSackShifted: 0
TCPSackMerged: 0
TCPSackShiftFallback: 0
TCPBacklogDrop: 0
TCPMinTTLDrop: 0
TCPDeferAcceptDrop: 0
IPReversePathFilter: 0
TCPTimeWaitOverflow: 0
TCPReqQFullDoCookies: 0
TCPReqQFullDrop: 0
IpExt:
InNoRoutes: 0
InTruncatedPkts: 0
InMcastPkts: 0
OutMcastPkts: 0
InBcastPkts: 0
OutBcastPkts: 0
InOctets: 11348
OutOctets: 3752
InMcastOctets: 0
OutMcastOctets: 0
InBcastOctets: 0
OutBcastOctets: 0
~ #
~ #
~ # tcpdump
device eth0 entered promiscuous mode
tcpdump: listening on eth0
00:01:31.421191 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:31.479686 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:31.442325 arp who-has 192.168.0.1 tell 192.168.0.100
00:01:31.446052 arp reply 192.168.0.1 is-at f4:ec:38:b2:6a:9e
00:01:31.446256 192.168.0.100.47044 > 192.168.0.1.53: 45191+ (44) (DF)
00:01:31.461859 192.168.0.1.53 > 192.168.0.100.47044: 45191 NXDomain 0/1/0 (121)
00:01:31.464125 192.168.0.100.41833 > 192.168.0.1.53: 37485+ (44) (DF)
00:01:31.478026 192.168.0.1.53 > 192.168.0.100.41833: 37485 NXDomain 0/1/0 (121)
00:01:31.481794 192.168.0.100.35138 > 192.168.0.1.53: 56594+ (42) (DF)
00:01:31.497202 192.168.0.1.53 > 192.168.0.100.35138: 56594 NXDomain 0/1/0 (119)
00:01:32.419130 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:32.419482 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:33.418342 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:33.418693 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:34.419327 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:34.419676 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:35.418042 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:35.418406 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:36.418923 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:36.419275 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:36.459936 arp who-has 192.168.0.100 tell 192.168.0.1
00:01:36.460216 arp reply 192.168.0.100 is-at 0:a:35:0:19:15
00:01:37.418800 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:37.419149 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:38.419247 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:38.419617 192.168.0.100 > 192.168.0.101: icmp: echo reply
00:01:39.418820 192.168.0.101 > 192.168.0.100: icmp: echo request (DF)
00:01:39.419169 192.168.0.100 > 192.168.0.101: icmp: echo reply
\x03
56 packets received by filter
0 packets droppeddevice eth0 left promiscuous mode
by kernel
~ #
~ # ping 192.168.0.101
PING 192.168.0.101 (192.168.0.101): 56 data bytes
\x03
--- 192.168.0.101 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
~ # ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
\x03
--- 192.168.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
~ # ping 192.168.0.101 -c 10 &
~ # PING 192.168.0.101 (192.168.0.101): 56 data bytes
~ # tcpdump
device eth0 entered promiscuous mode
tcpdump: listening on eth0
00:01:59.615918 192.168.0.100 > 192.168.0.101: icmp: echo request (DF)
00:01:59.619166 192.168.0.101 > 192.168.0.100: icmp: echo reply
00:01:59.636473 192.168.0.100.57212 > 192.168.0.1.53: 43026+ (44) (DF)
00:01:59.650838 192.168.0.1.53 > 192.168.0.100.57212: 43026 NXDomain 0/1/0 (121)
00:01:59.652915 192.168.0.100.41475 > 192.168.0.1.53: 28371+ (44) (DF)
00:01:59.666907 192.168.0.1.53 > 192.168.0.100.41475: 28371 NXDomain 0/1/0 (121)
00:01:59.670832 192.168.0.100.47770 > 192.168.0.1.53: 61908+ (42) (DF)
00:01:59.684921 192.168.0.1.53 > 192.168.0.100.47770: 61908 NXDomain 0/1/0 (119)
00:02:00.616493 192.168.0.100 > 192.168.0.101: icmp: echo request (DF)
00:02:00.620237 192.168.0.101 > 192.168.0.100: icmp: echo reply
00:02:00.624275 arp who-has 192.168.0.101 tell 192.168.0.100
00:02:00.627936 arp reply 192.168.0.101 is-at 0:22:15:fb:34:a1
00:02:01.617232 192.168.0.100 > 192.168.0.101: icmp: echo request (DF)
00:02:01.620980 192.168.0.101 > 192.168.0.100: icmp: echo reply
00:02:02.617962 192.168.0.100 > 192.168.0.101: icmp: echo request (DF)
00:02:02.621687 192.168.0.101 > 192.168.0.100: icmp: echo reply
00:02:03.618687 192.168.0.100 > 192.168.0.101: icmp: echo request (DF)
00:02:03.622389 192.168.0.101 > 192.168.0.100: icmp: echo reply
00:02:04.619414 192.168.0.100 > 192.168.0.101: icmp: echo request (DF)
00:02:04.623129 192.168.0.101 > 192.168.0.100: icmp: echo reply
42 packets received by filter
0 packets droppeddevice eth0 left promiscuous mode
by kernel
~ #
--- 192.168.0.101 ping statistics ---
10 packets transmitted, 0 packets received, 100% packet loss
[1] + Done(1) ping 192.168.0.101 -c 10
~ #
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply
* [PATCH net-next] sch_sfq: rehash queues in perturb timer
From: Eric Dumazet @ 2011-12-21 13:30 UTC (permalink / raw)
To: David Miller; +Cc: netdev
A known Out Of Order (OOO) problem hurts SFQ when timer changes
perturbation value, since all new packets delivered to SFQ enqueue might
end on different slots than previous in-flight packets.
With round robin delivery, we can thus deliver packets in a different
order.
Since SFQ is limited to small amount of in-flight packets, we can rehash
packets so that this OOO problem is fixed.
This rehashing is performed only if internal flow classifier is in use.
We now store in skb->cb[] the "struct flow_keys" so that we dont call
skb_flow_dissect() again while rehashing.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/sched/sch_sfq.c | 87 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 81 insertions(+), 6 deletions(-)
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 30cda70..d329a8a 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -136,16 +136,30 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index
return &q->dep[val - SFQ_SLOTS];
}
+/*
+ * In order to be able to quickly rehash our queue when timer changes
+ * q->perturbation, we store flow_keys in skb->cb[]
+ */
+struct sfq_skb_cb {
+ struct flow_keys keys;
+};
+
+static inline struct sfq_skb_cb *sfq_skb_cb(const struct sk_buff *skb)
+{
+ BUILD_BUG_ON(sizeof(skb->cb) <
+ sizeof(struct qdisc_skb_cb) + sizeof(struct sfq_skb_cb));
+ return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;
+}
+
static unsigned int sfq_hash(const struct sfq_sched_data *q,
const struct sk_buff *skb)
{
- struct flow_keys keys;
+ const struct flow_keys *keys = &sfq_skb_cb(skb)->keys;
unsigned int hash;
- skb_flow_dissect(skb, &keys);
- hash = jhash_3words((__force u32)keys.dst,
- (__force u32)keys.src ^ keys.ip_proto,
- (__force u32)keys.ports, q->perturbation);
+ hash = jhash_3words((__force u32)keys->dst,
+ (__force u32)keys->src ^ keys->ip_proto,
+ (__force u32)keys->ports, q->perturbation);
return hash & (q->divisor - 1);
}
@@ -161,8 +175,10 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
TC_H_MIN(skb->priority) <= q->divisor)
return TC_H_MIN(skb->priority);
- if (!q->filter_list)
+ if (!q->filter_list) {
+ skb_flow_dissect(skb, &sfq_skb_cb(skb)->keys);
return sfq_hash(q, skb) + 1;
+ }
*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
result = tc_classify(skb, q->filter_list, &res);
@@ -423,12 +439,71 @@ sfq_reset(struct Qdisc *sch)
kfree_skb(skb);
}
+/*
+ * When q->perturbation is changed, we rehash all queued skbs
+ * to avoid OOO (Out Of Order) effects.
+ * We dont use sfq_dequeue()/sfq_enqueue() because we dont want to change
+ * counters.
+ */
+static void sfq_rehash(struct sfq_sched_data *q)
+{
+ struct sk_buff *skb;
+ int i;
+ struct sfq_slot *slot;
+ struct sk_buff_head list;
+
+ __skb_queue_head_init(&list);
+
+ for (i = 0; i < SFQ_SLOTS; i++) {
+ slot = &q->slots[i];
+ if (!slot->qlen)
+ continue;
+ while (slot->qlen) {
+ skb = slot_dequeue_head(slot);
+ sfq_dec(q, i);
+ __skb_queue_tail(&list, skb);
+ }
+ q->ht[slot->hash] = SFQ_EMPTY_SLOT;
+ }
+ q->tail = NULL;
+
+ while ((skb = __skb_dequeue(&list)) != NULL) {
+ unsigned int hash = sfq_hash(q, skb);
+ sfq_index x = q->ht[hash];
+
+ slot = &q->slots[x];
+ if (x == SFQ_EMPTY_SLOT) {
+ x = q->dep[0].next; /* get a free slot */
+ q->ht[hash] = x;
+ slot = &q->slots[x];
+ slot->hash = hash;
+ }
+ slot_queue_add(slot, skb);
+ sfq_inc(q, x);
+ if (slot->qlen == 1) { /* The flow is new */
+ if (q->tail == NULL) { /* It is the first flow */
+ slot->next = x;
+ } else {
+ slot->next = q->tail->next;
+ q->tail->next = x;
+ }
+ q->tail = slot;
+ slot->allot = q->scaled_quantum;
+ }
+ }
+}
+
static void sfq_perturbation(unsigned long arg)
{
struct Qdisc *sch = (struct Qdisc *)arg;
struct sfq_sched_data *q = qdisc_priv(sch);
+ spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
+ spin_lock(root_lock);
q->perturbation = net_random();
+ if (!q->filter_list && q->tail)
+ sfq_rehash(q);
+ spin_unlock(root_lock);
if (q->perturb_period)
mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
^ permalink raw reply related
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 13:40 UTC (permalink / raw)
To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1DF00.1090309@monstr.eu>
Le mercredi 21 décembre 2011 à 14:28 +0100, Michal Simek a écrit :
> ok. Can you provide me any background why size should be setup by
> size = SKB_WITH_OVERHEAD(ksize(data));
> and not to use size which is passed to kmalloc in __alloc_skb.
Its all about memory accounting (based on skb->truesize)
Prior to the patch, we could fool memory accounting because skbs claimed
to use less memory than what they really used.
And crash machines eventually.
Now memory accouting is fixed, we probably need to change some points in
the kernel, where we previously accepted a small skb, but not a very
large one.
Since "ping" probably uses SOCK_RAW sockets, I'll try this one :
(We dont care of _this_ skb truesize, only on the count of previously
queued packets)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 0da505c..a809a48 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1631,8 +1631,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
if (snaplen > res)
snaplen = res;
- if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
- (unsigned)sk->sk_rcvbuf)
+ if (atomic_read(&sk->sk_rmem_alloc) >= (unsigned)sk->sk_rcvbuf)
goto drop_n_acct;
if (skb_shared(skb)) {
@@ -1763,7 +1762,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
if (po->tp_version <= TPACKET_V2) {
if (macoff + snaplen > po->rx_ring.frame_size) {
if (po->copy_thresh &&
- atomic_read(&sk->sk_rmem_alloc) + skb->truesize
+ atomic_read(&sk->sk_rmem_alloc)
< (unsigned)sk->sk_rcvbuf) {
if (skb_shared(skb)) {
copy_skb = skb_clone(skb, GFP_ATOMIC);
^ permalink raw reply related
* Re: [PATCH 0/4] skb paged fragment destructors
From: Ian Campbell @ 2011-12-21 13:48 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, jesse.brandeburg@intel.com, netdev@vger.kernel.org
In-Reply-To: <1324470605.2728.42.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On Wed, 2011-12-21 at 12:30 +0000, Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 11:18 +0000, Ian Campbell a écrit :
>
> >
> > An order 1 allocation is in multiples of PAGE_SIZE, isn't it, even
> > though they happen to be contiguous?
>
> Really an order-1 allocation allocates one page, a compound one.
Oh, right, I see what you mean.
You snipped the question about the + 2, I take it you have no idea what
it is all about either?
Ian.
^ permalink raw reply
* stmmac: updating the driver to the Dec 2011 version and add the PCI support
From: Giuseppe CAVALLARO @ 2011-12-21 13:56 UTC (permalink / raw)
To: ML netdev; +Cc: Rayagond K, David S. Miller
Hello.
This patches update the stmmac device driver to the latest version (Dec
2011) adding the experimental PCI support - thanks to the effort on
developing and testing done by Rayagond Kokatanur.
I'm sending the patches for both net and net-next repositories.
In the next updates, I hope in January, I will send the EEE and PTP
support (always thanks to Rayagond contribution).
In the end, the driver's documentation has been updated too.
Best Regards
Peppe
^ permalink raw reply
* [PATCH 1/2 (net.git)] stmmac: add the experimental PCI support
From: Giuseppe CAVALLARO @ 2011-12-21 13:58 UTC (permalink / raw)
To: netdev; +Cc: davem, rayagond, Giuseppe Cavallaro
In-Reply-To: <4EF1E582.5050300@st.com>
This patch adds the PCI support (as EXPERIMENTAL)
this has been also tested on XLINX XC2V3000 FF1152AMT0221
D1215994A VIRTEX FPGA board.
To support the PCI bus the main part has been reworked
and both the platform and the PCI specific parts have
been moved into different files.
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 27 ++-
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +
drivers/net/ethernet/stmicro/stmmac/common.h | 7 +
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 13 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 13 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 440 ++++++--------------
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 221 ++++++++++
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 217 ++++++++++
9 files changed, 631 insertions(+), 312 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 22745d7..0364283 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -12,11 +12,36 @@ config STMMAC_ETH
if STMMAC_ETH
+config STMMAC_PLATFORM
+ tristate "STMMAC platform bus support"
+ depends on STMMAC_ETH
+ default y
+ ---help---
+ This selects the platform specific bus support for
+ the stmmac device driver. This is the driver used
+ on many embedded STM platforms based on ARM and SuperH
+ processors.
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
+config STMMAC_PCI
+ tristate "STMMAC support on PCI bus (EXPERIMENTAL)"
+ depends on STMMAC_ETH && PCI && EXPERIMENTAL
+ ---help---
+ This is to select the Synopsys DWMAC available on PCI devices,
+ if you have a controller with this interface, say Y or M here.
+
+ This PCI support is tested on XLINX XC2V3000 FF1152AMT0221
+ D1215994A VIRTEX FPGA board.
+
+ If unsure, say N.
+
config STMMAC_DEBUG_FS
bool "Enable monitoring via sysFS "
default n
depends on STMMAC_ETH && DEBUG_FS
- -- help
+ ---help---
The stmmac entry in /sys reports DMA TX/RX rings
or (if supported) the HW cap register.
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index d7c4516..bc965ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -2,6 +2,8 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
+stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
+stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 2cc1192..d0b814e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -22,7 +22,11 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <linux/etherdevice.h>
#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/module.h>
+#include <linux/init.h>
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define STMMAC_VLAN_TAG_USED
#include <linux/if_vlan.h>
@@ -315,5 +319,8 @@ extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
unsigned int high, unsigned int low);
extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low);
+
+extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);
+
extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
extern const struct stmmac_ring_mode_ops ring_mode_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index e250935..f20aa12 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -238,6 +238,19 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
writel(data, ioaddr + low);
}
+/* Enable disable MAC RX/TX */
+void stmmac_set_mac(void __iomem *ioaddr, bool enable)
+{
+ u32 value = readl(ioaddr + MAC_CTRL_REG);
+
+ if (enable)
+ value |= MAC_RNABLE_RX | MAC_ENABLE_TX;
+ else
+ value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX);
+
+ writel(value, ioaddr + MAC_CTRL_REG);
+}
+
void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a140a8f..1207400 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -20,7 +20,8 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
-#define DRV_MODULE_VERSION "Oct_2011"
+#define STMMAC_RESOURCE_NAME "stmmaceth"
+#define DRV_MODULE_VERSION "Dec_2011"
#include <linux/stmmac.h>
#include <linux/phy.h>
#include "common.h"
@@ -82,8 +83,18 @@ struct stmmac_priv {
int hw_cap_support;
};
+extern int phyaddr;
+
extern int stmmac_mdio_unregister(struct net_device *ndev);
extern int stmmac_mdio_register(struct net_device *ndev);
extern void stmmac_set_ethtool_ops(struct net_device *netdev);
extern const struct stmmac_desc_ops enh_desc_ops;
extern const struct stmmac_desc_ops ndesc_ops;
+
+int stmmac_freeze(struct net_device *ndev);
+int stmmac_restore(struct net_device *ndev);
+int stmmac_resume(struct net_device *ndev);
+int stmmac_suspend(struct net_device *ndev);
+int stmmac_dvr_remove(struct net_device *ndev);
+struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ struct plat_stmmacenet_data *plat_dat);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 72cd190..1bb4e27 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -28,12 +28,8 @@
https://bugzilla.stlinux.com/
*******************************************************************************/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
-#include <linux/etherdevice.h>
-#include <linux/platform_device.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
@@ -52,8 +48,6 @@
#endif
#include "stmmac.h"
-#define STMMAC_RESOURCE_NAME "stmmaceth"
-
#undef STMMAC_DEBUG
/*#define STMMAC_DEBUG*/
#ifdef STMMAC_DEBUG
@@ -93,7 +87,7 @@ static int debug = -1; /* -1: default, 0: no output, 16: all */
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Message Level (0: no output, 16: all)");
-static int phyaddr = -1;
+int phyaddr = -1;
module_param(phyaddr, int, S_IRUGO);
MODULE_PARM_DESC(phyaddr, "Physical device address");
@@ -141,6 +135,11 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
+#ifdef CONFIG_STMMAC_DEBUG_FS
+static int stmmac_init_fs(struct net_device *dev);
+static void stmmac_exit_fs(void);
+#endif
+
/**
* stmmac_verify_args - verify the driver parameters.
* Description: it verifies if some wrong parameter is passed to the driver.
@@ -345,22 +344,6 @@ static int stmmac_init_phy(struct net_device *dev)
return 0;
}
-static inline void stmmac_enable_mac(void __iomem *ioaddr)
-{
- u32 value = readl(ioaddr + MAC_CTRL_REG);
-
- value |= MAC_RNABLE_RX | MAC_ENABLE_TX;
- writel(value, ioaddr + MAC_CTRL_REG);
-}
-
-static inline void stmmac_disable_mac(void __iomem *ioaddr)
-{
- u32 value = readl(ioaddr + MAC_CTRL_REG);
-
- value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX);
- writel(value, ioaddr + MAC_CTRL_REG);
-}
-
/**
* display_ring
* @p: pointer to the ring.
@@ -887,6 +870,53 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
}
/**
+ * stmmac_mac_device_setup
+ * @dev : device pointer
+ * Description: this is to attach the GMAC or MAC 10/100
+ * main core structures that will be completed during the
+ * open step.
+ */
+static int stmmac_mac_device_setup(struct net_device *dev)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+ struct mac_device_info *device;
+
+ if (priv->plat->has_gmac)
+ device = dwmac1000_setup(priv->ioaddr);
+ else
+ device = dwmac100_setup(priv->ioaddr);
+
+ if (!device)
+ return -ENOMEM;
+
+ priv->hw = device;
+ priv->hw->ring = &ring_mode_ops;
+
+ if (device_can_wakeup(priv->device)) {
+ priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
+ enable_irq_wake(priv->wol_irq);
+ }
+
+ return 0;
+}
+
+static void stmmac_check_ether_addr(struct stmmac_priv *priv)
+{
+ /* verify if the MAC address is valid, in case of failures it
+ * generates a random MAC address */
+ if (!is_valid_ether_addr(priv->dev->dev_addr)) {
+ priv->hw->mac->get_umac_addr((void __iomem *)
+ priv->dev->base_addr,
+ priv->dev->dev_addr, 0);
+ if (!is_valid_ether_addr(priv->dev->dev_addr))
+ random_ether_addr(priv->dev->dev_addr);
+ }
+ pr_warning("%s: device MAC address %pM\n", priv->dev->name,
+ priv->dev->dev_addr);
+}
+
+/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
* Description:
@@ -900,18 +930,28 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
- /* Check that the MAC address is valid. If its not, refuse
- * to bring the device up. The user must specify an
- * address using the following linux command:
- * ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */
- if (!is_valid_ether_addr(dev->dev_addr)) {
- random_ether_addr(dev->dev_addr);
- pr_warning("%s: generated random MAC address %pM\n", dev->name,
- dev->dev_addr);
- }
+ /* MAC HW device setup */
+ ret = stmmac_mac_device_setup(dev);
+ if (ret < 0)
+ return ret;
+
+ stmmac_check_ether_addr(priv);
stmmac_verify_args();
+ /* Override with kernel parameters if supplied XXX CRS XXX
+ * this needs to have multiple instances */
+ if ((phyaddr >= 0) && (phyaddr <= 31))
+ priv->plat->phy_addr = phyaddr;
+
+ /* MDIO bus Registration */
+ ret = stmmac_mdio_register(dev);
+ if (ret < 0) {
+ pr_debug("%s: MDIO bus (id: %d) registration failed",
+ __func__, priv->plat->bus_id);
+ return ret;
+ }
+
#ifdef CONFIG_STMMAC_TIMER
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
if (unlikely(priv->tm == NULL)) {
@@ -1008,7 +1048,7 @@ static int stmmac_open(struct net_device *dev)
}
/* Enable the MAC Rx/Tx */
- stmmac_enable_mac(priv->ioaddr);
+ stmmac_set_mac(priv->ioaddr, true);
/* Set the HW DMA mode and the COE */
stmmac_dma_operation_mode(priv);
@@ -1019,6 +1059,11 @@ static int stmmac_open(struct net_device *dev)
stmmac_mmc_setup(priv);
+#ifdef CONFIG_STMMAC_DEBUG_FS
+ ret = stmmac_init_fs(dev);
+ if (ret < 0)
+ pr_warning("\tFailed debugFS registration");
+#endif
/* Start the ball rolling... */
DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
priv->hw->dma->start_tx(priv->ioaddr);
@@ -1091,10 +1136,15 @@ static int stmmac_release(struct net_device *dev)
free_dma_desc_resources(priv);
/* Disable the MAC Rx/Tx */
- stmmac_disable_mac(priv->ioaddr);
+ stmmac_set_mac(priv->ioaddr, false);
netif_carrier_off(dev);
+#ifdef CONFIG_STMMAC_DEBUG_FS
+ stmmac_exit_fs();
+#endif
+ stmmac_mdio_unregister(dev);
+
return 0;
}
@@ -1738,28 +1788,41 @@ static const struct net_device_ops stmmac_netdev_ops = {
};
/**
- * stmmac_probe - Initialization of the adapter .
- * @dev : device pointer
- * Description: The function initializes the network device structure for
- * the STMMAC driver. It also calls the low level routines
- * in order to init the HW (i.e. the DMA engine)
+ * stmmac_dvr_probe
+ * @device: device pointer
+ * Description: this is the main probe function used to
+ * call the alloc_etherdev, allocate the priv structure.
*/
-static int stmmac_probe(struct net_device *dev)
+struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ struct plat_stmmacenet_data *plat_dat)
{
int ret = 0;
- struct stmmac_priv *priv = netdev_priv(dev);
+ struct net_device *ndev = NULL;
+ struct stmmac_priv *priv;
+
+ ndev = alloc_etherdev(sizeof(struct stmmac_priv));
+ if (!ndev) {
+ pr_err("%s: ERROR: allocating the device\n", __func__);
+ return NULL;
+ }
+
+ SET_NETDEV_DEV(ndev, device);
- ether_setup(dev);
+ priv = netdev_priv(ndev);
+ priv->device = device;
+ priv->dev = ndev;
- dev->netdev_ops = &stmmac_netdev_ops;
- stmmac_set_ethtool_ops(dev);
+ ether_setup(ndev);
- dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
- dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
- dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+ ndev->netdev_ops = &stmmac_netdev_ops;
+ stmmac_set_ethtool_ops(ndev);
+
+ ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */
- dev->features |= NETIF_F_HW_VLAN_RX;
+ ndev->features |= NETIF_F_HW_VLAN_RX;
#endif
priv->msg_enable = netif_msg_init(debug, default_msg_level);
@@ -1767,248 +1830,60 @@ static int stmmac_probe(struct net_device *dev)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
priv->pause = pause;
- netif_napi_add(dev, &priv->napi, stmmac_poll, 64);
-
- /* Get the MAC address */
- priv->hw->mac->get_umac_addr((void __iomem *) dev->base_addr,
- dev->dev_addr, 0);
-
- if (!is_valid_ether_addr(dev->dev_addr))
- pr_warning("\tno valid MAC address;"
- "please, use ifconfig or nwhwconfig!\n");
+ priv->plat = plat_dat;
+ netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
spin_lock_init(&priv->lock);
spin_lock_init(&priv->tx_lock);
- ret = register_netdev(dev);
+ ret = register_netdev(ndev);
if (ret) {
pr_err("%s: ERROR %i registering the device\n",
__func__, ret);
- return -ENODEV;
+ goto error;
}
DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
- dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
- (dev->features & NETIF_F_IP_CSUM) ? "on" : "off");
-
- return ret;
-}
-
-/**
- * stmmac_mac_device_setup
- * @dev : device pointer
- * Description: select and initialise the mac device (mac100 or Gmac).
- */
-static int stmmac_mac_device_setup(struct net_device *dev)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
-
- struct mac_device_info *device;
-
- if (priv->plat->has_gmac) {
- dev->priv_flags |= IFF_UNICAST_FLT;
- device = dwmac1000_setup(priv->ioaddr);
- } else {
- device = dwmac100_setup(priv->ioaddr);
- }
+ ndev->name, (ndev->features & NETIF_F_SG) ? "on" : "off",
+ (ndev->features & NETIF_F_IP_CSUM) ? "on" : "off");
- if (!device)
- return -ENOMEM;
-
- priv->hw = device;
- priv->hw->ring = &ring_mode_ops;
-
- if (device_can_wakeup(priv->device)) {
- priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
- enable_irq_wake(priv->wol_irq);
- }
-
- return 0;
-}
-
-/**
- * stmmac_dvr_probe
- * @pdev: platform device pointer
- * Description: the driver is initialized through platform_device.
- */
-static int stmmac_dvr_probe(struct platform_device *pdev)
-{
- int ret = 0;
- struct resource *res;
- void __iomem *addr = NULL;
- struct net_device *ndev = NULL;
- struct stmmac_priv *priv = NULL;
- struct plat_stmmacenet_data *plat_dat;
-
- pr_info("STMMAC driver:\n\tplatform registration... ");
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
- pr_info("\tdone!\n");
-
- if (!request_mem_region(res->start, resource_size(res),
- pdev->name)) {
- pr_err("%s: ERROR: memory allocation failed"
- "cannot get the I/O addr 0x%x\n",
- __func__, (unsigned int)res->start);
- return -EBUSY;
- }
-
- addr = ioremap(res->start, resource_size(res));
- if (!addr) {
- pr_err("%s: ERROR: memory mapping failed\n", __func__);
- ret = -ENOMEM;
- goto out_release_region;
- }
-
- ndev = alloc_etherdev(sizeof(struct stmmac_priv));
- if (!ndev) {
- pr_err("%s: ERROR: allocating the device\n", __func__);
- ret = -ENOMEM;
- goto out_unmap;
- }
-
- SET_NETDEV_DEV(ndev, &pdev->dev);
-
- /* Get the MAC information */
- ndev->irq = platform_get_irq_byname(pdev, "macirq");
- if (ndev->irq == -ENXIO) {
- pr_err("%s: ERROR: MAC IRQ configuration "
- "information not found\n", __func__);
- ret = -ENXIO;
- goto out_free_ndev;
- }
-
- priv = netdev_priv(ndev);
- priv->device = &(pdev->dev);
- priv->dev = ndev;
- plat_dat = pdev->dev.platform_data;
-
- priv->plat = plat_dat;
-
- priv->ioaddr = addr;
-
- /*
- * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
- * The external wake up irq can be passed through the platform code
- * named as "eth_wake_irq"
- *
- * In case the wake up interrupt is not passed from the platform
- * so the driver will continue to use the mac irq (ndev->irq)
- */
- priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
- if (priv->wol_irq == -ENXIO)
- priv->wol_irq = ndev->irq;
-
- platform_set_drvdata(pdev, ndev);
-
- /* Set the I/O base addr */
- ndev->base_addr = (unsigned long)addr;
-
- /* Custom initialisation */
- if (priv->plat->init) {
- ret = priv->plat->init(pdev);
- if (unlikely(ret))
- goto out_free_ndev;
- }
-
- /* MAC HW device detection */
- ret = stmmac_mac_device_setup(ndev);
- if (ret < 0)
- goto out_plat_exit;
+ return priv;
- /* Network Device Registration */
- ret = stmmac_probe(ndev);
- if (ret < 0)
- goto out_plat_exit;
-
- /* Override with kernel parameters if supplied XXX CRS XXX
- * this needs to have multiple instances */
- if ((phyaddr >= 0) && (phyaddr <= 31))
- priv->plat->phy_addr = phyaddr;
-
- pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
- "\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
- pdev->id, ndev->irq, addr);
+error:
+ netif_napi_del(&priv->napi);
- /* MDIO bus Registration */
- pr_debug("\tMDIO bus (id: %d)...", priv->plat->bus_id);
- ret = stmmac_mdio_register(ndev);
- if (ret < 0)
- goto out_unregister;
- pr_debug("registered!\n");
-
-#ifdef CONFIG_STMMAC_DEBUG_FS
- ret = stmmac_init_fs(ndev);
- if (ret < 0)
- pr_warning("\tFailed debugFS registration");
-#endif
-
- return 0;
-
-out_unregister:
unregister_netdev(ndev);
-out_plat_exit:
- if (priv->plat->exit)
- priv->plat->exit(pdev);
-out_free_ndev:
free_netdev(ndev);
- platform_set_drvdata(pdev, NULL);
-out_unmap:
- iounmap(addr);
-out_release_region:
- release_mem_region(res->start, resource_size(res));
- return ret;
+ return NULL;
}
/**
* stmmac_dvr_remove
- * @pdev: platform device pointer
+ * @ndev: net device pointer
* Description: this function resets the TX/RX processes, disables the MAC RX/TX
- * changes the link status, releases the DMA descriptor rings,
- * unregisters the MDIO bus and unmaps the allocated memory.
+ * changes the link status, releases the DMA descriptor rings.
*/
-static int stmmac_dvr_remove(struct platform_device *pdev)
+int stmmac_dvr_remove(struct net_device *ndev)
{
- struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
- struct resource *res;
pr_info("%s:\n\tremoving driver", __func__);
priv->hw->dma->stop_rx(priv->ioaddr);
priv->hw->dma->stop_tx(priv->ioaddr);
- stmmac_disable_mac(priv->ioaddr);
-
+ stmmac_set_mac(priv->ioaddr, false);
netif_carrier_off(ndev);
-
- stmmac_mdio_unregister(ndev);
-
- if (priv->plat->exit)
- priv->plat->exit(pdev);
-
- platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
-
- iounmap((void *)priv->ioaddr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
-#ifdef CONFIG_STMMAC_DEBUG_FS
- stmmac_exit_fs();
-#endif
-
free_netdev(ndev);
return 0;
}
#ifdef CONFIG_PM
-static int stmmac_suspend(struct device *dev)
+int stmmac_suspend(struct net_device *ndev)
{
- struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
int dis_ic = 0;
@@ -2042,15 +1917,14 @@ static int stmmac_suspend(struct device *dev)
if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
else
- stmmac_disable_mac(priv->ioaddr);
+ stmmac_set_mac(priv->ioaddr, false);
spin_unlock(&priv->lock);
return 0;
}
-static int stmmac_resume(struct device *dev)
+int stmmac_resume(struct net_device *ndev)
{
- struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
if (!netif_running(ndev))
@@ -2069,7 +1943,7 @@ static int stmmac_resume(struct device *dev)
netif_device_attach(ndev);
/* Enable the MAC and DMA */
- stmmac_enable_mac(priv->ioaddr);
+ stmmac_set_mac(priv->ioaddr, true);
priv->hw->dma->start_tx(priv->ioaddr);
priv->hw->dma->start_rx(priv->ioaddr);
@@ -2089,68 +1963,23 @@ static int stmmac_resume(struct device *dev)
return 0;
}
-static int stmmac_freeze(struct device *dev)
+int stmmac_freeze(struct net_device *ndev)
{
- struct net_device *ndev = dev_get_drvdata(dev);
-
if (!ndev || !netif_running(ndev))
return 0;
return stmmac_release(ndev);
}
-static int stmmac_restore(struct device *dev)
+int stmmac_restore(struct net_device *ndev)
{
- struct net_device *ndev = dev_get_drvdata(dev);
-
if (!ndev || !netif_running(ndev))
return 0;
return stmmac_open(ndev);
}
-
-static const struct dev_pm_ops stmmac_pm_ops = {
- .suspend = stmmac_suspend,
- .resume = stmmac_resume,
- .freeze = stmmac_freeze,
- .thaw = stmmac_restore,
- .restore = stmmac_restore,
-};
-#else
-static const struct dev_pm_ops stmmac_pm_ops;
#endif /* CONFIG_PM */
-static struct platform_driver stmmac_driver = {
- .probe = stmmac_dvr_probe,
- .remove = stmmac_dvr_remove,
- .driver = {
- .name = STMMAC_RESOURCE_NAME,
- .owner = THIS_MODULE,
- .pm = &stmmac_pm_ops,
- },
-};
-
-/**
- * stmmac_init_module - Entry point for the driver
- * Description: This function is the entry point for the driver.
- */
-static int __init stmmac_init_module(void)
-{
- int ret;
-
- ret = platform_driver_register(&stmmac_driver);
- return ret;
-}
-
-/**
- * stmmac_cleanup_module - Cleanup routine for the driver
- * Description: This function is the cleanup routine for the driver.
- */
-static void __exit stmmac_cleanup_module(void)
-{
- platform_driver_unregister(&stmmac_driver);
-}
-
#ifndef MODULE
static int __init stmmac_cmdline_opt(char *str)
{
@@ -2209,10 +2038,3 @@ err:
__setup("stmmaceth=", stmmac_cmdline_opt);
#endif
-
-module_init(stmmac_init_module);
-module_exit(stmmac_cleanup_module);
-
-MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet driver");
-MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 9c3b9d5..51f4412 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -109,6 +109,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
*/
static int stmmac_mdio_reset(struct mii_bus *bus)
{
+#if defined(CONFIG_STMMAC_PLATFORM)
struct net_device *ndev = bus->priv;
struct stmmac_priv *priv = netdev_priv(ndev);
unsigned int mii_address = priv->hw->mii.addr;
@@ -123,7 +124,7 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
* on MDC, so perform a dummy mdio read.
*/
writel(0, priv->ioaddr + mii_address);
-
+#endif
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
new file mode 100644
index 0000000..54a819a
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ This contains the functions to handle the pci driver.
+
+ Copyright (C) 2011-2012 Vayavya Labs Pvt Ltd
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/pci.h>
+#include "stmmac.h"
+
+struct plat_stmmacenet_data plat_dat;
+struct stmmac_mdio_bus_data mdio_data;
+
+static void stmmac_default_data(void)
+{
+ memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
+ plat_dat.bus_id = 1;
+ plat_dat.phy_addr = 0;
+ plat_dat.interface = PHY_INTERFACE_MODE_GMII;
+ plat_dat.pbl = 32;
+ plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+ plat_dat.has_gmac = 1;
+ plat_dat.force_sf_dma_mode = 1;
+
+ mdio_data.bus_id = 1;
+ mdio_data.phy_reset = NULL;
+ mdio_data.phy_mask = 0;
+ plat_dat.mdio_bus_data = &mdio_data;
+}
+
+/**
+ * stmmac_pci_probe
+ *
+ * @pdev: pci device pointer
+ * @id: pointer to table of device id/id's.
+ *
+ * Description: This probing function gets called for all PCI devices which
+ * match the ID table and are not "owned" by other driver yet. This function
+ * gets passed a "struct pci_dev *" for each device whose entry in the ID table
+ * matches the device. The probe functions returns zero when the driver choose
+ * to take "ownership" of the device or an error code(-ve no) otherwise.
+ */
+static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int ret = 0;
+ void __iomem *addr = NULL;
+ struct stmmac_priv *priv = NULL;
+ int i;
+
+ /* Enable pci device */
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ pr_err("%s : ERROR: failed to enable %s device\n", __func__,
+ pci_name(pdev));
+ return ret;
+ }
+ if (pci_request_regions(pdev, STMMAC_RESOURCE_NAME)) {
+ pr_err("%s: ERROR: failed to get PCI region\n", __func__);
+ ret = -ENODEV;
+ goto err_out_req_reg_failed;
+ }
+
+ /* Get the base address of device */
+ for (i = 0; i <= 5; i++) {
+ if (pci_resource_len(pdev, i) == 0)
+ continue;
+ addr = pci_iomap(pdev, i, 0);
+ if (addr == NULL) {
+ pr_err("%s: ERROR: cannot map regiser memory, aborting",
+ __func__);
+ ret = -EIO;
+ goto err_out_map_failed;
+ }
+ break;
+ }
+ pci_set_master(pdev);
+
+ stmmac_default_data();
+
+ priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat);
+ if (!priv) {
+ pr_err("%s: main drivr probe failed", __func__);
+ goto err_out;
+ }
+ priv->ioaddr = addr;
+ priv->dev->base_addr = (unsigned long)addr;
+ priv->dev->irq = pdev->irq;
+ priv->wol_irq = pdev->irq;
+
+ pci_set_drvdata(pdev, priv->dev);
+
+ pr_debug("STMMAC platform driver registration completed");
+
+ return 0;
+
+err_out:
+ pci_clear_master(pdev);
+err_out_map_failed:
+ pci_release_regions(pdev);
+err_out_req_reg_failed:
+ pci_disable_device(pdev);
+
+ return ret;
+}
+
+/**
+ * stmmac_dvr_remove
+ *
+ * @pdev: platform device pointer
+ * Description: this function calls the main to free the net resources
+ * and releases the PCI resources.
+ */
+static void __devexit stmmac_pci_remove(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+
+ stmmac_dvr_remove(ndev);
+
+ pci_set_drvdata(pdev, NULL);
+ pci_iounmap(pdev, priv->ioaddr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int stmmac_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ int ret;
+
+ ret = stmmac_suspend(ndev);
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return ret;
+}
+
+static int stmmac_pci_resume(struct pci_dev *pdev)
+{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ return stmmac_resume(ndev);
+}
+#endif
+
+#define STMMAC_VENDOR_ID 0x700
+#define STMMAC_DEVICE_ID 0x1108
+
+static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
+ {
+ PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, {
+ }
+};
+
+MODULE_DEVICE_TABLE(pci, stmmac_id_table);
+
+static struct pci_driver stmmac_driver = {
+ .name = STMMAC_RESOURCE_NAME,
+ .id_table = stmmac_id_table,
+ .probe = stmmac_pci_probe,
+ .remove = __devexit_p(stmmac_pci_remove),
+#ifdef CONFIG_PM
+ .suspend = stmmac_pci_suspend,
+ .resume = stmmac_pci_resume,
+#endif
+};
+
+/**
+ * stmmac_init_module - Entry point for the driver
+ * Description: This function is the entry point for the driver.
+ */
+static int __init stmmac_init_module(void)
+{
+ int ret;
+
+ ret = pci_register_driver(&stmmac_driver);
+ if (ret < 0)
+ pr_err("%s: ERROR: driver registration failed\n", __func__);
+
+ return ret;
+}
+
+/**
+ * stmmac_cleanup_module - Cleanup routine for the driver
+ * Description: This function is the cleanup routine for the driver.
+ */
+static void __exit stmmac_cleanup_module(void)
+{
+ pci_unregister_driver(&stmmac_driver);
+}
+
+module_init(stmmac_init_module);
+module_exit(stmmac_cleanup_module);
+
+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
+MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
new file mode 100644
index 0000000..54d391c
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ This contains the functions to handle the platform driver.
+
+ Copyright (C) 2007-2011 STMicroelectronics Ltd
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include "stmmac.h"
+
+/**
+ * stmmac_pltfr_probe
+ * @pdev: platform device pointer
+ * Description: platform_device probe function. It allocates
+ * the necessary resources and invokes the main to init
+ * the net device, register the mdio bus etc.
+ */
+static int stmmac_pltfr_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res;
+ void __iomem *addr = NULL;
+ struct stmmac_priv *priv = NULL;
+ struct plat_stmmacenet_data *plat_dat;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+ pr_err("%s: ERROR: memory allocation failed"
+ "cannot get the I/O addr 0x%x\n",
+ __func__, (unsigned int)res->start);
+ return -EBUSY;
+ }
+
+ addr = ioremap(res->start, resource_size(res));
+ if (!addr) {
+ pr_err("%s: ERROR: memory mapping failed", __func__);
+ ret = -ENOMEM;
+ goto out_release_region;
+ }
+ plat_dat = pdev->dev.platform_data;
+ priv = stmmac_dvr_probe(&(pdev->dev), plat_dat);
+ if (!priv) {
+ pr_err("%s: main drivr probe failed", __func__);
+ goto out_release_region;
+ }
+
+ priv->ioaddr = addr;
+ /* Set the I/O base addr */
+ priv->dev->base_addr = (unsigned long)addr;
+
+ /* Get the MAC information */
+ priv->dev->irq = platform_get_irq_byname(pdev, "macirq");
+ if (priv->dev->irq == -ENXIO) {
+ pr_err("%s: ERROR: MAC IRQ configuration "
+ "information not found\n", __func__);
+ ret = -ENXIO;
+ goto out_unmap;
+ }
+
+ /*
+ * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
+ * The external wake up irq can be passed through the platform code
+ * named as "eth_wake_irq"
+ *
+ * In case the wake up interrupt is not passed from the platform
+ * so the driver will continue to use the mac irq (ndev->irq)
+ */
+ priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
+ if (priv->wol_irq == -ENXIO)
+ priv->wol_irq = priv->dev->irq;
+
+ platform_set_drvdata(pdev, priv->dev);
+
+ /* Custom initialisation */
+ if (priv->plat->init) {
+ ret = priv->plat->init(pdev);
+ if (unlikely(ret))
+ goto out_unmap;
+ }
+
+ pr_debug("STMMAC platform driver registration completed");
+
+ return 0;
+
+out_unmap:
+ iounmap(addr);
+ platform_set_drvdata(pdev, NULL);
+
+out_release_region:
+ release_mem_region(res->start, resource_size(res));
+
+ return ret;
+}
+
+/**
+ * stmmac_pltfr_remove
+ * @pdev: platform device pointer
+ * Description: this function calls the main to free the net resources
+ * and calls the platforms hook and release the resources (e.g. mem).
+ */
+static int stmmac_pltfr_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct resource *res;
+ int ret = stmmac_dvr_remove(ndev);
+
+ if (priv->plat->exit)
+ priv->plat->exit(pdev);
+
+ if (priv->plat->exit)
+ priv->plat->exit(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ iounmap((void *)priv->ioaddr);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int stmmac_pltfr_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ return stmmac_suspend(ndev);
+}
+
+static int stmmac_pltfr_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ return stmmac_resume(ndev);
+}
+
+int stmmac_pltfr_freeze(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ return stmmac_freeze(ndev);
+}
+
+int stmmac_pltfr_restore(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ return stmmac_restore(ndev);
+}
+
+static const struct dev_pm_ops stmmac_pltfr_pm_ops = {
+ .suspend = stmmac_pltfr_suspend,
+ .resume = stmmac_pltfr_resume,
+ .freeze = stmmac_pltfr_freeze,
+ .thaw = stmmac_pltfr_restore,
+ .restore = stmmac_pltfr_restore,
+};
+#else
+static const struct dev_pm_ops stmmac_pltfr_pm_ops;
+#endif /* CONFIG_PM */
+
+static struct platform_driver stmmac_driver = {
+ .probe = stmmac_pltfr_probe,
+ .remove = stmmac_pltfr_remove,
+ .driver = {
+ .name = STMMAC_RESOURCE_NAME,
+ .owner = THIS_MODULE,
+ .pm = &stmmac_pltfr_pm_ops,
+ },
+};
+
+/**
+ * stmmac_init_module - Entry point for the driver
+ * Description: This function is the entry point for the driver.
+ */
+static int __init stmmac_init_module(void)
+{
+ return platform_driver_register(&stmmac_driver);
+}
+
+/**
+ * stmmac_cleanup_module - Cleanup routine for the driver
+ * Description: This function is the cleanup routine for the driver.
+ */
+static void __exit stmmac_cleanup_module(void)
+{
+ platform_driver_unregister(&stmmac_driver);
+}
+
+module_init(stmmac_init_module);
+module_exit(stmmac_cleanup_module);
+
+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
--
1.7.4.4
^ permalink raw reply related
* [PATCH 2/2 (net.git)] stmmac: update the driver's documentation (Dec-2011)
From: Giuseppe CAVALLARO @ 2011-12-21 13:58 UTC (permalink / raw)
To: netdev; +Cc: davem, rayagond, Giuseppe Cavallaro
In-Reply-To: <1324475900-1470-1-git-send-email-peppe.cavallaro@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
Documentation/networking/stmmac.txt | 16 +++++++++-------
1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 8d67980..d0aeead 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -4,14 +4,16 @@ Copyright (C) 2007-2010 STMicroelectronics Ltd
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
-(Synopsys IP blocks); it has been fully tested on STLinux platforms.
+(Synopsys IP blocks).
Currently this network device driver is for all STM embedded MAC/GMAC
-(i.e. 7xxx/5xxx SoCs) and it's known working on other platforms i.e. ARM SPEAr.
+(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000
+FF1152AMT0221 D1215994A VIRTEX FPGA board.
-DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100
-Universal version 4.0 have been used for developing the first code
-implementation.
+DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100
+Universal version 4.0 have been used for developing this driver.
+
+This driver supports both the platform bus and PCI.
Please, for more information also visit: www.stlinux.com
@@ -277,5 +279,5 @@ In fact, these can generate an huge amount of debug messages.
6) TODO:
o XGMAC is not supported.
- o Review the timer optimisation code to use an embedded device that will be
- available in new chip generations.
+ o Add the EEE - Energy Efficient Ethernet
+ o Add the PTP - precision time protocol
--
1.7.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox