* Re: [PATCH] RDSRDMA: Fix cleanup of rds_iw_mr_pool
From: David Miller @ 2011-09-27 5:32 UTC (permalink / raw)
To: jonathan; +Cc: venkat.x.venkatsubra, netdev
In-Reply-To: <20110913194101.7497.65515.stgit@build.ogc.int>
From: Jonathan Lallinger <jonathan@ogc.us>
Date: Tue, 13 Sep 2011 14:41:01 -0500
> @@ -548,6 +550,7 @@ static int rds_iw_flush_mr_pool(struct rds_iw_mr_pool *pool, int free_all)
> spin_unlock_irqrestore(&pool->list_lock, flags);
> }
>
> + atomic_sub(unpinned, &poll->free_pinned);
> atomic_sub(ncleaned, &pool->dirty_count);
> atomic_sub(nfreed, &pool->item_count);
>
net/rds/iw_rdma.c: In function ‘rds_iw_flush_mr_pool’:
net/rds/iw_rdma.c:553:24: error: ‘poll’ undeclared (first use in this function)
net/rds/iw_rdma.c:553:24: note: each undeclared identifier is reported only once for each function it appears in
If you didn't even build test it, I know you didn't test it's
functionality either.
This is crazy.
Well if it's not important enough to even build test this change
before you post it, then it obviously doesn't matter if the RDMA
module crashes the kernel when it's unloaded.
^ permalink raw reply
* Re: Question about memory leak detector giving false positive report for net/core/flow.c
From: Eric Dumazet @ 2011-09-27 5:55 UTC (permalink / raw)
To: Huajun Li
Cc: Catalin Marinas, linux-mm@kvack.org, netdev, linux-kernel,
Tejun Heo, Christoph Lameter
In-Reply-To: <CA+v9cxYzWJScCa2mMoEovq3WULSZYQaq6EjoRV7SQUjr0L_RiQ@mail.gmail.com>
Le mardi 27 septembre 2011 à 13:29 +0800, Huajun Li a écrit :
> 2011/9/27 Eric Dumazet <eric.dumazet@gmail.com>:
> > Le lundi 26 septembre 2011 à 17:50 +0100, Catalin Marinas a écrit :
> >> On Mon, Sep 26, 2011 at 05:32:54PM +0100, Eric Dumazet wrote:
> >> > Le lundi 26 septembre 2011 à 23:17 +0800, Huajun Li a écrit :
> >> > > Memory leak detector gives following memory leak report, it seems the
> >> > > report is triggered by net/core/flow.c, but actually, it should be a
> >> > > false positive report.
> >> > > So, is there any idea from kmemleak side to fix/disable this false
> >> > > positive report like this?
> >> > > Yes, kmemleak_not_leak(...) could disable it, but is it suitable for this case ?
> >> ...
> >> > CC lkml and percpu maintainers (Tejun Heo & Christoph Lameter ) as well
> >> >
> >> > AFAIK this false positive only occurs if percpu data is allocated
> >> > outside of embedded pcu space.
> >> >
> >> > (grep pcpu_get_vm_areas /proc/vmallocinfo)
> >> >
> >> > I suspect this is a percpu/kmemleak cooperation problem (a missing
> >> > kmemleak_alloc() ?)
> >> >
> >> > I am pretty sure kmemleak_not_leak() is not the right answer to this
> >> > problem.
> >>
> >> kmemleak_not_leak() definitely not the write answer. The alloc_percpu()
> >> call does not have any kmemleak_alloc() callback, so it doesn't scan
> >> them.
> >>
> >> Huajun, could you please try the patch below:
> >>
> >> 8<--------------------------------
> >> kmemleak: Handle percpu memory allocation
> >>
> >> From: Catalin Marinas <catalin.marinas@arm.com>
> >>
> >> This patch adds kmemleak callbacks from the percpu allocator, reducing a
> >> number of false positives caused by kmemleak not scanning such memory
> >> blocks.
> >>
> >> Reported-by: Huajun Li <huajun.li.lee@gmail.com>
> >> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> >> ---
> >> mm/percpu.c | 11 +++++++++--
> >> 1 files changed, 9 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/mm/percpu.c b/mm/percpu.c
> >> index bf80e55..c47a90b 100644
> >> --- a/mm/percpu.c
> >> +++ b/mm/percpu.c
> >> @@ -67,6 +67,7 @@
> >> #include <linux/spinlock.h>
> >> #include <linux/vmalloc.h>
> >> #include <linux/workqueue.h>
> >> +#include <linux/kmemleak.h>
> >>
> >> #include <asm/cacheflush.h>
> >> #include <asm/sections.h>
> >> @@ -833,7 +834,9 @@ fail_unlock_mutex:
> >> */
> >> void __percpu *__alloc_percpu(size_t size, size_t align)
> >> {
> >> - return pcpu_alloc(size, align, false);
> >> + void __percpu *ptr = pcpu_alloc(size, align, false);
> >> + kmemleak_alloc(ptr, size, 1, GFP_KERNEL);
> >> + return ptr;
> >> }
> >> EXPORT_SYMBOL_GPL(__alloc_percpu);
> >>
> >> @@ -855,7 +858,9 @@ EXPORT_SYMBOL_GPL(__alloc_percpu);
> >> */
> >> void __percpu *__alloc_reserved_percpu(size_t size, size_t align)
> >> {
> >> - return pcpu_alloc(size, align, true);
> >> + void __percpu *ptr = pcpu_alloc(size, align, true);
> >> + kmemleak_alloc(ptr, size, 1, GFP_KERNEL);
> >> + return ptr;
> >> }
> >>
> >> /**
> >> @@ -915,6 +920,8 @@ void free_percpu(void __percpu *ptr)
> >> if (!ptr)
> >> return;
> >>
> >> + kmemleak_free(ptr);
> >> +
> >> addr = __pcpu_ptr_to_addr(ptr);
> >>
> >> spin_lock_irqsave(&pcpu_lock, flags);
> >>
> >
> > Hmm, you need to call kmemleak_alloc() for each chunk allocated per
> > possible cpu.
> >
> > Here is the (untested) patch for the allocation phase, need the same at
> > freeing time
> >
> > diff --git a/mm/percpu-km.c b/mm/percpu-km.c
> > index 89633fe..5061ac5 100644
> > --- a/mm/percpu-km.c
> > +++ b/mm/percpu-km.c
> > @@ -37,9 +37,12 @@ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size)
> > {
> > unsigned int cpu;
> >
> > - for_each_possible_cpu(cpu)
> > - memset((void *)pcpu_chunk_addr(chunk, cpu, 0) + off, 0, size);
> > + for_each_possible_cpu(cpu) {
> > + void *chunk_addr = (void *)pcpu_chunk_addr(chunk, cpu, 0) + off;
> >
> > + kmemleak_alloc(chunk_addr, size, 1, GFP_KERNEL);
> > + memset(chunk_addr, 0, size);
> > + }
> > return 0;
> > }
> >
> > diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c
> > index ea53496..0d397cc 100644
> > --- a/mm/percpu-vm.c
> > +++ b/mm/percpu-vm.c
> > @@ -342,8 +342,12 @@ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size)
> > /* commit new bitmap */
> > bitmap_copy(chunk->populated, populated, pcpu_unit_pages);
> > clear:
> > - for_each_possible_cpu(cpu)
> > - memset((void *)pcpu_chunk_addr(chunk, cpu, 0) + off, 0, size);
> > + for_each_possible_cpu(cpu) {
> > + void *chunk_addr = (void *)pcpu_chunk_addr(chunk, cpu, 0) + off;
> > +
> > + kmemleak_alloc(chunk_addr, size, 1, GFP_KERNEL);
> > + memset(chunk_addr, 0, size);
> > + }
> > return 0;
> >
> > err_unmap:
> >
> >
>
> About this one, memory leak detector disabled(actually I enable it
> while config the kernel) while booting system, and and found following
> info in dmesg:
Yes, it was not a patch, but the general idea for Catalin ;)
You hit the fact that same zone (embedded percpu space) is now in a
mixed state.
In current kernels, the embedded percpu zone is already known by
kmemleak, but with a large granularity. kmemleak is not aware of
individual allocations/freeing in this large zone.
Once kmemleak and percpu allocator are cooperating, we might find more
kmemleaks. Right now, kmemleak can find pointers in percpu chunks that
are not anymore reachable (they were freed), and therefore doesnt warn
of possible memory leaks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Eric Dumazet @ 2011-09-27 6:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <20110927.005905.1166544891922183065.davem@davemloft.net>
struct tcp_skb_cb contains a "flags" field containing either tcp flags
or IP dsfield depending on context (input or output path)
Introduce ip_dsfield to make the difference clear and ease maintenance.
If later we want to save space, we can union flags/ip_dsfield
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
If there is no objection, I plan to rename "flags" to "tcp_flags" in a
following patch.
include/net/tcp.h | 3 ++-
net/ipv4/tcp_input.c | 2 +-
net/ipv4/tcp_ipv4.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +-
4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 702aefc..28a9997 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -642,7 +642,8 @@ struct tcp_skb_cb {
#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
#define TCPCB_LOST 0x04 /* SKB is lost */
#define TCPCB_TAGBITS 0x07 /* All tag bits */
-
+ __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */
+ /* 1 byte hole */
#define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */
#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 5a4408c..7008fcc 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -222,7 +222,7 @@ static inline void TCP_ECN_check_ce(struct tcp_sock *tp, const struct sk_buff *s
if (!(tp->ecn_flags & TCP_ECN_OK))
return;
- switch (TCP_SKB_CB(skb)->flags & INET_ECN_MASK) {
+ switch (TCP_SKB_CB(skb)->ip_dsfield & INET_ECN_MASK) {
case INET_ECN_NOT_ECT:
/* Funny extension: if ECT is not set on a segment,
* and we already seen ECT on a previous segment,
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c29912c..dd3fad9 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1677,7 +1677,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
skb->len - th->doff * 4);
TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
TCP_SKB_CB(skb)->when = 0;
- TCP_SKB_CB(skb)->flags = iph->tos;
+ TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
TCP_SKB_CB(skb)->sacked = 0;
sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 12bdb9a..00797d8 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1717,7 +1717,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
skb->len - th->doff*4);
TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
TCP_SKB_CB(skb)->when = 0;
- TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr);
+ TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
TCP_SKB_CB(skb)->sacked = 0;
sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
^ permalink raw reply related
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: David Miller @ 2011-09-27 6:20 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <1317103249.2796.25.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 27 Sep 2011 08:00:49 +0200
> struct tcp_skb_cb contains a "flags" field containing either tcp flags
> or IP dsfield depending on context (input or output path)
>
> Introduce ip_dsfield to make the difference clear and ease maintenance.
> If later we want to save space, we can union flags/ip_dsfield
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied, thanks Eric.
> If there is no objection, I plan to rename "flags" to "tcp_flags" in a
> following patch.
No objections.
^ permalink raw reply
* Re: [PATCH 1/2] virtio-net: Verify page list size before fitting into skb
From: Sasha Levin @ 2011-09-27 6:44 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: linux-kernel, Rusty Russell, virtualization, netdev, kvm
In-Reply-To: <20110926195541.GA23086@redhat.com>
On Mon, 2011-09-26 at 22:55 +0300, Michael S. Tsirkin wrote:
> On Mon, Sep 26, 2011 at 10:37:22PM +0300, Sasha Levin wrote:
> > On Mon, 2011-09-26 at 21:44 +0300, Michael S. Tsirkin wrote:
> > > On Mon, Sep 26, 2011 at 08:41:08PM +0300, Sasha Levin wrote:
> > > > This patch verifies that the length of a buffer stored in a linked list
> > > > of pages is small enough to fit into a skb.
> > > >
> > > > If the size is larger than a max size of a skb, it means that we shouldn't
> > > > go ahead building skbs anyway since we won't be able to send the buffer as
> > > > the user requested.
> > > >
> > > > Cc: Rusty Russell <rusty@rustcorp.com.au>
> > > > Cc: "Michael S. Tsirkin" <mst@redhat.com>
> > > > Cc: virtualization@lists.linux-foundation.org
> > > > Cc: netdev@vger.kernel.org
> > > > Cc: kvm@vger.kernel.org
> > > > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> > >
> > > Interesting. This is a theoretical issue, correct?
> > > Not a crash you actually see.
> >
> > Actually it was an actual crash caused when our virtio-net driver in kvm
> > tools did funny things and passed '(u32)-1' length as a buffer length to
> > the guest kernel.
> >
> > > This crash would mean device is giving us packets
> > > that are way too large. Avoiding crashes even in the face of
> > > a misbehaved device is a good idea, but should
> > > we print a diagnostic to a system log?
> > > Maybe rate-limited or print once to avoid filling
> > > up the disk. Other places in driver print with pr_debug
> > > I'm not sure that's right but better than nothing.
> >
> > Yup, I'll add some debug info.
> >
> > > > ---
> > > > drivers/net/virtio_net.c | 3 +++
> > > > 1 files changed, 3 insertions(+), 0 deletions(-)
> > > >
> > > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > > > index 0c7321c..64e0717 100644
> > > > --- a/drivers/net/virtio_net.c
> > > > +++ b/drivers/net/virtio_net.c
> > > > @@ -165,6 +165,9 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
> > > > unsigned int copy, hdr_len, offset;
> > > > char *p;
> > > >
> > > > + if (len > MAX_SKB_FRAGS * PAGE_SIZE)
> > >
> > > unlikely()?
> > >
> > > Also, this seems too aggressive: at this point len includes the header
> > > and the linear part. The right place for this
> > > test is probably where we fill in the frags, just before
> > > while (len)
> > >
> > > The whole can only happen when mergeable buffers
> > > are disabled, right?
> >
> > >From what I understand it can happen whenever you're going to build a
> > skb longer than PAGE_SIZE.
>
> Hmm how exactly? With mergeable buffers this only gets
> the length of the 1st chunk which is up to 4K unless the driver
> is buggy ...
What about the case where TSO or ECN features are set? The code flow
suggests that mergeable would get ignored in that case:
/* If we can receive ANY GSO packets, we must allocate large ones. */
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
vi->big_packets = true;
[...]
if (!vi->mergeable_rx_bufs && !vi->big_packets) {
skb = buf;
len -= sizeof(struct virtio_net_hdr);
skb_trim(skb, len);
} else {
page = buf;
skb = page_to_skb(vi, page, len);
...
I haven't actually tested it with mergeable buffers enabled, but could
do it later today.
--
Sasha.
^ permalink raw reply
* [patch] 9p: fix min_t() casting in p9pdu_vwritef()
From: Dan Carpenter @ 2011-09-27 6:44 UTC (permalink / raw)
To: Eric Van Hensbergen
Cc: David S. Miller, Eric Van Hensbergen, Venkateswararao Jujjuri,
Aneesh Kumar K.V, Harsh Prateek Bora, netdev, kernel-janitors
I don't think we're actually likely to hit this limit but if we do
then the comparison should be done as size_t. The original code
is equivalent to:
len = strlen(sptr) % USHRT_MAX;
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 55e10a9..39a4c18 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -368,7 +368,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
const char *sptr = va_arg(ap, const char *);
uint16_t len = 0;
if (sptr)
- len = min_t(uint16_t, strlen(sptr),
+ len = min_t(size_t, strlen(sptr),
USHRT_MAX);
errcode = p9pdu_writef(pdu, proto_version,
^ permalink raw reply related
* Re: [PATCH 1/2] virtio-net: Verify page list size before fitting into skb
From: Michael S. Tsirkin @ 2011-09-27 7:00 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-kernel, Rusty Russell, virtualization, netdev, kvm
In-Reply-To: <1317105842.3467.3.camel@lappy>
On Tue, Sep 27, 2011 at 09:44:02AM +0300, Sasha Levin wrote:
> On Mon, 2011-09-26 at 22:55 +0300, Michael S. Tsirkin wrote:
> > On Mon, Sep 26, 2011 at 10:37:22PM +0300, Sasha Levin wrote:
> > > On Mon, 2011-09-26 at 21:44 +0300, Michael S. Tsirkin wrote:
> > > > On Mon, Sep 26, 2011 at 08:41:08PM +0300, Sasha Levin wrote:
> > > > > This patch verifies that the length of a buffer stored in a linked list
> > > > > of pages is small enough to fit into a skb.
> > > > >
> > > > > If the size is larger than a max size of a skb, it means that we shouldn't
> > > > > go ahead building skbs anyway since we won't be able to send the buffer as
> > > > > the user requested.
> > > > >
> > > > > Cc: Rusty Russell <rusty@rustcorp.com.au>
> > > > > Cc: "Michael S. Tsirkin" <mst@redhat.com>
> > > > > Cc: virtualization@lists.linux-foundation.org
> > > > > Cc: netdev@vger.kernel.org
> > > > > Cc: kvm@vger.kernel.org
> > > > > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> > > >
> > > > Interesting. This is a theoretical issue, correct?
> > > > Not a crash you actually see.
> > >
> > > Actually it was an actual crash caused when our virtio-net driver in kvm
> > > tools did funny things and passed '(u32)-1' length as a buffer length to
> > > the guest kernel.
> > >
> > > > This crash would mean device is giving us packets
> > > > that are way too large. Avoiding crashes even in the face of
> > > > a misbehaved device is a good idea, but should
> > > > we print a diagnostic to a system log?
> > > > Maybe rate-limited or print once to avoid filling
> > > > up the disk. Other places in driver print with pr_debug
> > > > I'm not sure that's right but better than nothing.
> > >
> > > Yup, I'll add some debug info.
> > >
> > > > > ---
> > > > > drivers/net/virtio_net.c | 3 +++
> > > > > 1 files changed, 3 insertions(+), 0 deletions(-)
> > > > >
> > > > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > > > > index 0c7321c..64e0717 100644
> > > > > --- a/drivers/net/virtio_net.c
> > > > > +++ b/drivers/net/virtio_net.c
> > > > > @@ -165,6 +165,9 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
> > > > > unsigned int copy, hdr_len, offset;
> > > > > char *p;
> > > > >
> > > > > + if (len > MAX_SKB_FRAGS * PAGE_SIZE)
> > > >
> > > > unlikely()?
> > > >
> > > > Also, this seems too aggressive: at this point len includes the header
> > > > and the linear part. The right place for this
> > > > test is probably where we fill in the frags, just before
> > > > while (len)
> > > >
> > > > The whole can only happen when mergeable buffers
> > > > are disabled, right?
> > >
> > > >From what I understand it can happen whenever you're going to build a
> > > skb longer than PAGE_SIZE.
> >
> > Hmm how exactly? With mergeable buffers this only gets
> > the length of the 1st chunk which is up to 4K unless the driver
> > is buggy ...
>
> What about the case where TSO or ECN features are set? The code flow
> suggests that mergeable would get ignored in that case:
>
> /* If we can receive ANY GSO packets, we must allocate large ones. */
> if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
> virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
> virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
> vi->big_packets = true;
>
> [...]
>
> if (!vi->mergeable_rx_bufs && !vi->big_packets) {
> skb = buf;
> len -= sizeof(struct virtio_net_hdr);
> skb_trim(skb, len);
> } else {
> page = buf;
> skb = page_to_skb(vi, page, len);
> ...
Sorry I don't get it yet. Where is mergeable ignored here?
> I haven't actually tested it with mergeable buffers enabled, but could
> do it later today.
Please do.
> --
>
> Sasha.
^ permalink raw reply
* TSO support
From: Sedat Cakir @ 2011-09-27 7:19 UTC (permalink / raw)
To: netdev
Hi,
We are adding the TCP Segmentation offload (TSO) support to the device
driver and the hardware. I am wondering: Can Linux subsystem supports
the use of IP options and TCP options? If so then which options (e.g
SACK processing for TCP)? Do we need any implementation in the NIC to
manage TCP/IP options?
Thanks,
Sedat
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Christoph Paasch @ 2011-09-27 7:37 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <20110927.022025.1306291417181821045.davem@davemloft.net>
Hi,
I realize that before "struct tcp_skb_cb" is a comment saying that it's 44
bytes long.
However, (as far as I can see) before Eric's change it was 42 bytes long and
now it became 43 bytes.
Wouldn't it make sense to change the comment, so that it's consistent again
with the real size of tcp_skb_cb ?
Cheers,
Christoph
On Tuesday 27 September 2011 wrote David Miller:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Tue, 27 Sep 2011 08:00:49 +0200
>
> > struct tcp_skb_cb contains a "flags" field containing either tcp flags
> > or IP dsfield depending on context (input or output path)
> >
> > Introduce ip_dsfield to make the difference clear and ease maintenance.
> > If later we want to save space, we can union flags/ip_dsfield
> >
> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> Applied, thanks Eric.
>
> > If there is no objection, I plan to rename "flags" to "tcp_flags" in a
> > following patch.
>
> No objections.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Christoph Paasch
PhD Student
IP Networking Lab --- http://inl.info.ucl.ac.be
MultiPath TCP in the Linux Kernel --- http://inl.info.ucl.ac.be/mptcp
Université Catholique de Louvain
www.rollerbulls.be
--
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Eric Dumazet @ 2011-09-27 8:01 UTC (permalink / raw)
To: christoph.paasch; +Cc: David Miller, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <201109271037.38786.christoph.paasch@uclouvain.be>
Le mardi 27 septembre 2011 à 10:37 +0300, Christoph Paasch a écrit :
> Hi,
>
> I realize that before "struct tcp_skb_cb" is a comment saying that it's 44
> bytes long.
>
> However, (as far as I can see) before Eric's change it was 42 bytes long and
> now it became 43 bytes.
>
> Wouldn't it make sense to change the comment, so that it's consistent again
> with the real size of tcp_skb_cb ?
You are mistaken :)
There was a two bytes hole.
I took one byte for dsfield, and left one byte hole,
I added a comment to remind there is this hole
Thanks !
^ permalink raw reply
* Re: TSO support
From: Michio Honda @ 2011-09-27 8:00 UTC (permalink / raw)
To: Sedat Cakir; +Cc: netdev
In-Reply-To: <CAG+4w0mNdSwwQMH7+DSGUzMUrqjE_v7M55EP8Ug6JxytuJsN7g@mail.gmail.com>
Hi,
On TSO and TCP options, as far as I tested approx. 10 NICs, TSO copies TCP options to all the split segments. (We performed this test for Timestamp and an undefined option).
This paper (http://nrg.cs.ucl.ac.uk/mjh/tmp/mboxes.pdf) would be helpful.
Thanks,
- Michio
On Sep 27, 2011, at 4:19 PM, Sedat Cakir wrote:
> Hi,
>
> We are adding the TCP Segmentation offload (TSO) support to the device
> driver and the hardware. I am wondering: Can Linux subsystem supports
> the use of IP options and TCP options? If so then which options (e.g
> SACK processing for TCP)? Do we need any implementation in the NIC to
> manage TCP/IP options?
>
> Thanks,
> Sedat
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: David Miller @ 2011-09-27 8:08 UTC (permalink / raw)
To: christoph.paasch; +Cc: eric.dumazet, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <201109271037.38786.christoph.paasch@uclouvain.be>
From: Christoph Paasch <christoph.paasch@uclouvain.be>
Date: Tue, 27 Sep 2011 10:37:38 +0300
> However, (as far as I can see) before Eric's change it was 42 bytes long and
> now it became 43 bytes.
Then, I suggest that you go buy a pair of glasses. :-)
^ permalink raw reply
* Re: [GIT PULL net-next] IPVS
From: Pablo Neira Ayuso @ 2011-09-27 8:16 UTC (permalink / raw)
To: Simon Horman
Cc: lvs-devel, netdev, netfilter-devel, netfilter, Wensong Zhang,
Julian Anastasov, Patrick McHardy, David S. Miller
In-Reply-To: <1317027938-22053-1-git-send-email-horms@verge.net.au>
On Mon, Sep 26, 2011 at 06:05:33PM +0900, Simon Horman wrote:
> Hi,
>
> with all the excitement of kernel.org being offline and a bunch of trees
> likewise being offline I am a little unsure who should take this pull
> request which is based on the current net-next tree. But I guess it should
> be Patrick, Pablo or Dave.
I'll try to set up one tree in one of my servers along today, I'll
send you the URI. We can use it until kernel.org comes back.
@Patrick: Contact me and I'll create one account for you so we can
access the same tree.
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Christoph Paasch @ 2011-09-27 8:38 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <20110927.040853.516739403765881835.davem@davemloft.net>
On Tuesday 27 September 2011 wrote David Miller:
> From: Christoph Paasch <christoph.paasch@uclouvain.be>
> Date: Tue, 27 Sep 2011 10:37:38 +0300
>
> > However, (as far as I can see) before Eric's change it was 42 bytes long
> > and now it became 43 bytes.
>
> Then, I suggest that you go buy a pair of glasses. :-)
Yeah, maybe it's time to... ;-)
This two-byte hole, is it because "flags" and "sacked" are both __u8 and
fields are aligned to 32-bit ?
Thanks,
Christoph
--
Christoph Paasch
PhD Student
IP Networking Lab --- http://inl.info.ucl.ac.be
MultiPath TCP in the Linux Kernel --- http://inl.info.ucl.ac.be/mptcp
Université Catholique de Louvain
www.rollerbulls.be
--
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Eric Dumazet @ 2011-09-27 9:23 UTC (permalink / raw)
To: christoph.paasch; +Cc: David Miller, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <201109271138.00318.christoph.paasch@uclouvain.be>
Le mardi 27 septembre 2011 à 11:38 +0300, Christoph Paasch a écrit :
> On Tuesday 27 September 2011 wrote David Miller:
> > From: Christoph Paasch <christoph.paasch@uclouvain.be>
> > Date: Tue, 27 Sep 2011 10:37:38 +0300
> >
> > > However, (as far as I can see) before Eric's change it was 42 bytes long
> > > and now it became 43 bytes.
> >
> > Then, I suggest that you go buy a pair of glasses. :-)
>
> Yeah, maybe it's time to... ;-)
>
> This two-byte hole, is it because "flags" and "sacked" are both __u8 and
> fields are aligned to 32-bit ?
Not exactly.
Reason for the hole is the following :
struct whatever {
u8 first;
u8 second;
u32 third;
};
"third" field has an alignement requirement of 4 bytes on most arches.
Compiler inserts a 2 bytes hole before "third" to respect this
requirement.
There is no hole between "first" and "second", since second has no
alignment requirement.
sizeof(struct whatever) = 8
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Christoph Paasch @ 2011-09-27 9:28 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <1317115409.2541.6.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Eric,
On Tuesday 27 September 2011 wrote Eric Dumazet:
> Le mardi 27 septembre 2011 à 11:38 +0300, Christoph Paasch a écrit :
> > On Tuesday 27 September 2011 wrote David Miller:
> > This two-byte hole, is it because "flags" and "sacked" are both __u8 and
> > fields are aligned to 32-bit ?
>
> Not exactly.
>
> Reason for the hole is the following :
>
> struct whatever {
> u8 first;
> u8 second;
> u32 third;
> };
>
> "third" field has an alignement requirement of 4 bytes on most arches.
>
> Compiler inserts a 2 bytes hole before "third" to respect this
> requirement.
>
> There is no hole between "first" and "second", since second has no
> alignment requirement.
>
> sizeof(struct whatever) = 8
Ok, I understand.
Thanks for the info. I didn't knew this...
It's good news...
Maybe we win now a little bit of space in MultiPath TCP by rearranging our
fields... :-)
Cheers,
Christoph
--
Christoph Paasch
PhD Student
IP Networking Lab --- http://inl.info.ucl.ac.be
MultiPath TCP in the Linux Kernel --- http://inl.info.ucl.ac.be/mptcp
Université Catholique de Louvain
www.rollerbulls.be
--
^ permalink raw reply
* Re: [PATCH net-next] tcp: unalias tcp_skb_cb flags and ip_dsfield
From: Eric Dumazet @ 2011-09-27 9:40 UTC (permalink / raw)
To: christoph.paasch; +Cc: David Miller, netdev, hkchu, ilpo.jarvinen, jhs
In-Reply-To: <201109271228.44232.christoph.paasch@uclouvain.be>
Le mardi 27 septembre 2011 à 12:28 +0300, Christoph Paasch a écrit :
>
> Ok, I understand.
> Thanks for the info. I didn't knew this...
>
> It's good news...
> Maybe we win now a little bit of space in MultiPath TCP by rearranging our
> fields... :-)
To ease your task, I suggest you take a look at pahole
http://lwn.net/Articles/365844/
^ permalink raw reply
* [PATCH net-next] tcp: rename tcp_skb_cb flags
From: Eric Dumazet @ 2011-09-27 9:51 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110927.022025.1306291417181821045.davem@davemloft.net>
Rename struct tcp_skb_cb "flags" to "tcp_flags" to ease code review and
maintenance.
Its content is a combination of FIN/SYN/RST/PSH/ACK/URG/ECE/CWR flags
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/net/tcp.h | 2 -
net/ipv4/tcp.c | 8 ++---
net/ipv4/tcp_input.c | 4 +-
net/ipv4/tcp_output.c | 63 ++++++++++++++++++++--------------------
4 files changed, 39 insertions(+), 38 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 28a9997..0113d30 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -636,7 +636,7 @@ struct tcp_skb_cb {
__u32 seq; /* Starting sequence number */
__u32 end_seq; /* SEQ + FIN + SYN + datalen */
__u32 when; /* used to compute rtt's */
- __u8 flags; /* TCP header flags. */
+ __u8 tcp_flags; /* TCP header flags. (tcp[13]) */
__u8 sacked; /* State flags for SACK/FACK. */
#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */
#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index cc0d5de..131c45f 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -524,7 +524,7 @@ EXPORT_SYMBOL(tcp_ioctl);
static inline void tcp_mark_push(struct tcp_sock *tp, struct sk_buff *skb)
{
- TCP_SKB_CB(skb)->flags |= TCPHDR_PSH;
+ TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
tp->pushed_seq = tp->write_seq;
}
@@ -540,7 +540,7 @@ static inline void skb_entail(struct sock *sk, struct sk_buff *skb)
skb->csum = 0;
tcb->seq = tcb->end_seq = tp->write_seq;
- tcb->flags = TCPHDR_ACK;
+ tcb->tcp_flags = TCPHDR_ACK;
tcb->sacked = 0;
skb_header_release(skb);
tcp_add_write_queue_tail(sk, skb);
@@ -830,7 +830,7 @@ new_segment:
skb_shinfo(skb)->gso_segs = 0;
if (!copied)
- TCP_SKB_CB(skb)->flags &= ~TCPHDR_PSH;
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
copied += copy;
poffset += copy;
@@ -1074,7 +1074,7 @@ new_segment:
}
if (!copied)
- TCP_SKB_CB(skb)->flags &= ~TCPHDR_PSH;
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
tp->write_seq += copy;
TCP_SKB_CB(skb)->end_seq += copy;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 7008fcc..143221e 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1449,7 +1449,7 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
tp->lost_cnt_hint -= tcp_skb_pcount(prev);
}
- TCP_SKB_CB(skb)->flags |= TCP_SKB_CB(prev)->flags;
+ TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags;
if (skb == tcp_highest_sack(sk))
tcp_advance_highest_sack(sk, skb);
@@ -3348,7 +3348,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
* connection startup slow start one packet too
* quickly. This is severely frowned upon behavior.
*/
- if (!(scb->flags & TCPHDR_SYN)) {
+ if (!(scb->tcp_flags & TCPHDR_SYN)) {
flag |= FLAG_DATA_ACKED;
} else {
flag |= FLAG_SYN_ACKED;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 081dcd6..dde6b57 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -297,9 +297,9 @@ static u16 tcp_select_window(struct sock *sk)
/* Packet ECN state for a SYN-ACK */
static inline void TCP_ECN_send_synack(struct tcp_sock *tp, struct sk_buff *skb)
{
- TCP_SKB_CB(skb)->flags &= ~TCPHDR_CWR;
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_CWR;
if (!(tp->ecn_flags & TCP_ECN_OK))
- TCP_SKB_CB(skb)->flags &= ~TCPHDR_ECE;
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_ECE;
}
/* Packet ECN state for a SYN. */
@@ -309,7 +309,7 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb)
tp->ecn_flags = 0;
if (sysctl_tcp_ecn == 1) {
- TCP_SKB_CB(skb)->flags |= TCPHDR_ECE | TCPHDR_CWR;
+ TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_ECE | TCPHDR_CWR;
tp->ecn_flags = TCP_ECN_OK;
}
}
@@ -356,7 +356,7 @@ static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags)
skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum = 0;
- TCP_SKB_CB(skb)->flags = flags;
+ TCP_SKB_CB(skb)->tcp_flags = flags;
TCP_SKB_CB(skb)->sacked = 0;
skb_shinfo(skb)->gso_segs = 1;
@@ -826,7 +826,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
tcb = TCP_SKB_CB(skb);
memset(&opts, 0, sizeof(opts));
- if (unlikely(tcb->flags & TCPHDR_SYN))
+ if (unlikely(tcb->tcp_flags & TCPHDR_SYN))
tcp_options_size = tcp_syn_options(sk, skb, &opts, &md5);
else
tcp_options_size = tcp_established_options(sk, skb, &opts,
@@ -850,9 +850,9 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
th->seq = htonl(tcb->seq);
th->ack_seq = htonl(tp->rcv_nxt);
*(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) |
- tcb->flags);
+ tcb->tcp_flags);
- if (unlikely(tcb->flags & TCPHDR_SYN)) {
+ if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) {
/* RFC1323: The window in SYN & SYN/ACK segments
* is never scaled.
*/
@@ -875,7 +875,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
}
tcp_options_write((__be32 *)(th + 1), tp, &opts);
- if (likely((tcb->flags & TCPHDR_SYN) == 0))
+ if (likely((tcb->tcp_flags & TCPHDR_SYN) == 0))
TCP_ECN_send(sk, skb, tcp_header_size);
#ifdef CONFIG_TCP_MD5SIG
@@ -889,7 +889,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
icsk->icsk_af_ops->send_check(sk, skb);
- if (likely(tcb->flags & TCPHDR_ACK))
+ if (likely(tcb->tcp_flags & TCPHDR_ACK))
tcp_event_ack_sent(sk, tcp_skb_pcount(skb));
if (skb->len != tcp_header_size)
@@ -1032,9 +1032,9 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
/* PSH and FIN should only be set in the second packet. */
- flags = TCP_SKB_CB(skb)->flags;
- TCP_SKB_CB(skb)->flags = flags & ~(TCPHDR_FIN | TCPHDR_PSH);
- TCP_SKB_CB(buff)->flags = flags;
+ flags = TCP_SKB_CB(skb)->tcp_flags;
+ TCP_SKB_CB(skb)->tcp_flags = flags & ~(TCPHDR_FIN | TCPHDR_PSH);
+ TCP_SKB_CB(buff)->tcp_flags = flags;
TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked;
if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_PARTIAL) {
@@ -1340,7 +1340,8 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp,
u32 in_flight, cwnd;
/* Don't be strict about the congestion window for the final FIN. */
- if ((TCP_SKB_CB(skb)->flags & TCPHDR_FIN) && tcp_skb_pcount(skb) == 1)
+ if ((TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) &&
+ tcp_skb_pcount(skb) == 1)
return 1;
in_flight = tcp_packets_in_flight(tp);
@@ -1409,7 +1410,7 @@ static inline int tcp_nagle_test(struct tcp_sock *tp, struct sk_buff *skb,
* Nagle can be ignored during F-RTO too (see RFC4138).
*/
if (tcp_urg_mode(tp) || (tp->frto_counter == 2) ||
- (TCP_SKB_CB(skb)->flags & TCPHDR_FIN))
+ (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN))
return 1;
if (!tcp_nagle_check(tp, skb, cur_mss, nonagle))
@@ -1497,9 +1498,9 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
/* PSH and FIN should only be set in the second packet. */
- flags = TCP_SKB_CB(skb)->flags;
- TCP_SKB_CB(skb)->flags = flags & ~(TCPHDR_FIN | TCPHDR_PSH);
- TCP_SKB_CB(buff)->flags = flags;
+ flags = TCP_SKB_CB(skb)->tcp_flags;
+ TCP_SKB_CB(skb)->tcp_flags = flags & ~(TCPHDR_FIN | TCPHDR_PSH);
+ TCP_SKB_CB(buff)->tcp_flags = flags;
/* This packet was never sent out yet, so no SACK bits. */
TCP_SKB_CB(buff)->sacked = 0;
@@ -1530,7 +1531,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
u32 send_win, cong_win, limit, in_flight;
int win_divisor;
- if (TCP_SKB_CB(skb)->flags & TCPHDR_FIN)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
goto send_now;
if (icsk->icsk_ca_state != TCP_CA_Open)
@@ -1657,7 +1658,7 @@ static int tcp_mtu_probe(struct sock *sk)
TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
- TCP_SKB_CB(nskb)->flags = TCPHDR_ACK;
+ TCP_SKB_CB(nskb)->tcp_flags = TCPHDR_ACK;
TCP_SKB_CB(nskb)->sacked = 0;
nskb->csum = 0;
nskb->ip_summed = skb->ip_summed;
@@ -1677,11 +1678,11 @@ static int tcp_mtu_probe(struct sock *sk)
if (skb->len <= copy) {
/* We've eaten all the data from this skb.
* Throw it away. */
- TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags;
+ TCP_SKB_CB(nskb)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
tcp_unlink_write_queue(skb, sk);
sk_wmem_free_skb(sk, skb);
} else {
- TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags &
+ TCP_SKB_CB(nskb)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags &
~(TCPHDR_FIN|TCPHDR_PSH);
if (!skb_shinfo(skb)->nr_frags) {
skb_pull(skb, copy);
@@ -1987,7 +1988,7 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(next_skb)->end_seq;
/* Merge over control information. This moves PSH/FIN etc. over */
- TCP_SKB_CB(skb)->flags |= TCP_SKB_CB(next_skb)->flags;
+ TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(next_skb)->tcp_flags;
/* All done, get rid of second SKB and account for it so
* packet counting does not break.
@@ -2035,7 +2036,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
if (!sysctl_tcp_retrans_collapse)
return;
- if (TCP_SKB_CB(skb)->flags & TCPHDR_SYN)
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
return;
tcp_for_write_queue_from_safe(skb, tmp, sk) {
@@ -2127,12 +2128,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
* since it is cheap to do so and saves bytes on the network.
*/
if (skb->len > 0 &&
- (TCP_SKB_CB(skb)->flags & TCPHDR_FIN) &&
+ (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) &&
tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
if (!pskb_trim(skb, 0)) {
/* Reuse, even though it does some unnecessary work */
tcp_init_nondata_skb(skb, TCP_SKB_CB(skb)->end_seq - 1,
- TCP_SKB_CB(skb)->flags);
+ TCP_SKB_CB(skb)->tcp_flags);
skb->ip_summed = CHECKSUM_NONE;
}
}
@@ -2322,7 +2323,7 @@ void tcp_send_fin(struct sock *sk)
mss_now = tcp_current_mss(sk);
if (tcp_send_head(sk) != NULL) {
- TCP_SKB_CB(skb)->flags |= TCPHDR_FIN;
+ TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN;
TCP_SKB_CB(skb)->end_seq++;
tp->write_seq++;
} else {
@@ -2384,11 +2385,11 @@ int tcp_send_synack(struct sock *sk)
struct sk_buff *skb;
skb = tcp_write_queue_head(sk);
- if (skb == NULL || !(TCP_SKB_CB(skb)->flags & TCPHDR_SYN)) {
+ if (skb == NULL || !(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
printk(KERN_DEBUG "tcp_send_synack: wrong queue state\n");
return -EFAULT;
}
- if (!(TCP_SKB_CB(skb)->flags & TCPHDR_ACK)) {
+ if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_ACK)) {
if (skb_cloned(skb)) {
struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
if (nskb == NULL)
@@ -2402,7 +2403,7 @@ int tcp_send_synack(struct sock *sk)
skb = nskb;
}
- TCP_SKB_CB(skb)->flags |= TCPHDR_ACK;
+ TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_ACK;
TCP_ECN_send_synack(tcp_sk(sk), skb);
}
TCP_SKB_CB(skb)->when = tcp_time_stamp;
@@ -2799,13 +2800,13 @@ int tcp_write_wakeup(struct sock *sk)
if (seg_size < TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq ||
skb->len > mss) {
seg_size = min(seg_size, mss);
- TCP_SKB_CB(skb)->flags |= TCPHDR_PSH;
+ TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
if (tcp_fragment(sk, skb, seg_size, mss))
return -1;
} else if (!tcp_skb_pcount(skb))
tcp_set_skb_tso_segs(sk, skb, mss);
- TCP_SKB_CB(skb)->flags |= TCPHDR_PSH;
+ TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
if (!err)
^ permalink raw reply related
* Re: [PATCH 2/2] net: Fix potential memory leak
From: Huajun Li @ 2011-09-27 9:58 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, Huajun Li
In-Reply-To: <1317017353.2853.13.camel@edumazet-laptop>
2011/9/26 Eric Dumazet <eric.dumazet@gmail.com>:
> Le samedi 24 septembre 2011 à 23:57 +0800, Huajun Li a écrit :
>> While preparing flow caches, once fail may cause potential memory leak , fix it.
>>
>> Signed-off-by: Huajun Li <huajun.li.lee@gmail.com>
>> ---
>> net/core/flow.c | 19 ++++++++++++++++++-
>> 1 files changed, 18 insertions(+), 1 deletions(-)
>>
>> diff --git a/net/core/flow.c b/net/core/flow.c
>> index ba3e617..2dcaa03 100644
>> --- a/net/core/flow.c
>> +++ b/net/core/flow.c
>> @@ -420,7 +420,7 @@ static int __init flow_cache_init(struct flow_cache *fc)
>>
>> for_each_online_cpu(i) {
>> if (flow_cache_cpu_prepare(fc, i))
>> - return -ENOMEM;
>> + goto err;
>> }
>> fc->hotcpu_notifier = (struct notifier_block){
>> .notifier_call = flow_cache_cpu,
>> @@ -433,6 +433,23 @@ static int __init flow_cache_init(struct flow_cache *fc)
>> add_timer(&fc->rnd_timer);
>>
>> return 0;
>> +err:
>> + if (fc->percpu) {
>> + free_percpu(fc->percpu);
>> + fc->percpu = NULL;
>> + }
>> +
>> + /*
>> + * Check each possible CPUs rather than online ones because they may be
>> + * offline before the notifier is registered.
>> + */
>
> Please remove this comment.
>
>
>> + for_each_possible_cpu(i) {
>> + struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
>> + kfree(fcp->hash_table);
>> + fcp->hash_table = NULL;
>> + }
>
> You access fc->percpu after freeing it...
>
>> +
>> + return -ENOMEM;
>> }
>>
>> static int __init flow_cache_init_global(void)
>
> Previous to 2.6.37 (commit 83b6b1f5d134), a memory allocation at this
> stage was panicing the box, so no worry about mem leak :)
>
To emulate memory allocation fail case, I added code to return
'-ENOMEM' from flow_cache_cpu_prepare(...) even if it could allocate
memory correctly, but did not find panic on my box, maybe the latest
code changed greatly than 2.6.37. :)
^ permalink raw reply
* Re: [PATCH] w5300: add WIZnet W5300 Ethernet driver
From: Taehun Kim @ 2011-09-27 10:03 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel
In-Reply-To: <1316261666-28555-1-git-send-email-kth3321@gmail.com>
2011/9/17 Taehun Kim <kth3321@gmail.com>:
> WIZnet W5300 is a network chip into which 10/100 Ethernet controller, MAC, and TCP/IP are integrated.
> This driver supports just Ethernet function in W5300.
>
> Signed-off-by: Taehun Kim <kth3321@gmail.com>
> ---
> drivers/net/Kconfig | 5 +
> drivers/net/Makefile | 1 +
> drivers/net/w5300.c | 669 ++++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/net/w5300.h | 350 ++++++++++++++++++++++++++
> 4 files changed, 1025 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/w5300.c
> create mode 100644 drivers/net/w5300.h
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 8d0314d..4a8a100 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -2016,6 +2016,11 @@ config LANTIQ_ETOP
> help
> Support for the MII0 inside the Lantiq SoC
>
> +config W5300
> + tristate "WIZnet W5300 ethernet driver"
> + depends on ARM
> + help
> + This is driver for WIZnet W5300 network chip.
>
> source "drivers/net/fs_enet/Kconfig"
>
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index e1eca2a..288fce1 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -266,6 +266,7 @@ obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
> obj-$(CONFIG_DNET) += dnet.o
> obj-$(CONFIG_MACB) += macb.o
> obj-$(CONFIG_S6GMAC) += s6gmac.o
> +obj-$(CONFIG_W5300) += w5300.o
>
> obj-$(CONFIG_ARM) += arm/
> obj-$(CONFIG_DEV_APPLETALK) += appletalk/
> diff --git a/drivers/net/w5300.c b/drivers/net/w5300.c
> new file mode 100644
> index 0000000..fcc2579
> --- /dev/null
> +++ b/drivers/net/w5300.c
> @@ -0,0 +1,669 @@
> +/* w5300.c: A Linux Ethernet driver for the WIZnet W5300 chip. */
> +/*
> + Copyright (C) 2011 Taehun Kim <kth3321@gmail.com>
> +
> + This software may be used and distributed according to the terms of
> + the GNU General Public License (GPL), incorporated herein by reference.
> + Drivers based on or derived from this code fall under the GPL and must
> + retain the authorship, copyright and license notice. This file is not
> + a complete program and may only be used when the entire operating
> + system is licensed under the GPL.
> +*/
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/errno.h>
> +
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/skbuff.h>
> +
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/ioport.h>
> +#include <linux/io.h>
> +
> +#include "w5300.h"
> +
> +#define DEV_NAME "w5300"
> +#define DRV_VERSION "1.0"
> +#define DRV_RELDATE "Sept 17, 2011"
> +
> +static const char driver_info[] =
> + KERN_INFO DEV_NAME ": Ethernet driver v" DRV_VERSION "("
> + DRV_RELDATE ")\n";
> +
> +MODULE_AUTHOR("Taehun Kim <kth3321@gmail.com>");
> +MODULE_DESCRIPTION("WIZnet W5300 Ethernet driver");
> +MODULE_VERSION(DRV_VERSION);
> +MODULE_LICENSE("GPL");
> +
> +/* Transmit timeout, default 5 seconds. */
> +static int watchdog = 5000;
> +module_param(watchdog, int, 0400);
> +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
> +
> +/*
> + * This is W5300 information structure.
> + * Additional information is included in struct net_device.
> + */
> +struct wiz_private {
> + void __iomem *base;
> + struct net_device *dev;
> + u8 rxbuf_conf[MAX_SOCK_NUM];
> + u8 txbuf_conf[MAX_SOCK_NUM];
> + struct net_device_stats stats;
> + struct napi_struct napi;
> + spinlock_t lock;
> +};
> +
> +/* Default MAC address. */
> +static const u8 w5300_defmac[6] = {0x00, 0x08, 0xDC, 0xA0, 0x00, 0x01};
> +
> +/* Default RX/TX buffer size(KByte). */
> +static const u8 w5300_rxbuf_conf[MAX_SOCK_NUM] = { 64, 0, 0, 0, 0, 0, 0, 0 };
> +static const u8 w5300_txbuf_conf[MAX_SOCK_NUM] = { 64, 0, 0, 0, 0, 0, 0, 0 };
> +
> +/* Notifying packet size in the RX FIFO */
> +static int
> +w5300_get_rxsize(struct wiz_private *wp, int s)
> +{
> + u32 val;
> +
> + val = w5300_read(wp, Sn_RX_RSR(s));
> + val = (val << 16) + w5300_read(wp, Sn_RX_RSR2(s));
> + return val;
> +}
> +
> +/* Packet Receive Function. It reads received packet from the Rx FIFO. */
> +static int
> +w5300_recv_data(struct wiz_private *wp, int s,
> + u8 *buf, ssize_t len, int swap_enable)
> +{
> + int i;
> + u16 recv_data;
> +
> + if (unlikely(len <= 0))
> + return 0;
> +
> + if (swap_enable) {
> + /* read from RX FIFO */
> + for (i = 0; i < len; i += 2) {
> + recv_data = w5300_read(wp, Sn_RX_FIFO(s));
> + buf[i] = (u8) ((recv_data & 0xFF00) >> 8);
> + buf[i + 1] = (u8) (recv_data & 0x00FF);
> + }
> + } else {
> + for (i = 0; i < len; i += 2) {
> + recv_data = w5300_read(wp, Sn_RX_FIFO(s));
> + buf[i] = (u8) (recv_data & 0x00FF);
> + buf[i + 1] = (u8) ((recv_data & 0xFF00) >> 8);
> + }
> + }
> + return len;
> +}
> +
> +/* Setting MAC address of W5300 */
> +static void
> +w5300_set_macaddr(struct wiz_private *wp, u8 * addr)
> +{
> + w5300_write(wp, SHAR, (u16) (addr[0] << 8) | (u16) addr[1]);
> + w5300_write(wp, SHAR2, (u16) (addr[2] << 8) | (u16) addr[3]);
> + w5300_write(wp, SHAR4, (u16) (addr[4] << 8) | (u16) addr[5]);
> +}
> +
> +/* Opening channels of W5300 */
> +static int
> +w5300_open(struct wiz_private *wp, u32 type)
> +{
> + /* Which type will be used for open? */
> + switch (type) {
> + case Sn_MR_MACRAW:
> + case Sn_MR_MACRAW_MF:
> + w5300_write(wp, Sn_MR(0), type);
> + break;
> + default:
> + printk(KERN_ERR "%s: Unknown socket type (%d)\n",
> + DEV_NAME, type);
> + return -EFAULT;
> + }
> + w5300_write(wp, Sn_PORTR(0), 5300);
> +
> + w5300_write(wp, Sn_CR(0), Sn_CR_OPEN);
> + while (w5300_read(wp, Sn_CR(0)))
> + udelay(1);
> +
> + return 0;
> +}
> +
> +/* Activating the interrupt of related channel */
> +static void
> +w5300_interrupt_enable(struct wiz_private *wp, int s)
> +{
> + u16 mask;
> + mask = w5300_read(wp, IMR);
> + mask |= (0x01 << s);
> + w5300_write(wp, IMR, mask);
> +}
> +
> +/* De-activating the interrupt of related channel */
> +static void
> +w5300_interrupt_disable(struct wiz_private *wp, int s)
> +{
> + u16 mask;
> + mask = w5300_read(wp, IMR);
> + mask &= ~(0x01 << s);
> + w5300_write(wp, IMR, mask);
> +}
> +
> +/* W5300 initialization function */
> +static int
> +w5300_reset(struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> + u32 txbuf_total = 0, i;
> + u16 mem_cfg = 0;
> +
> + DPRINTK("%s: w5300 chip reset\n", __func__);
> +
> + /* W5300 is initialized by sending RESET command. */
> + w5300_write(wp, MR, MR_RST);
> + mdelay(5);
> +
> + /* Mode Register Setting
> + * Ping uses S/W stack of the Linux kernel. Set the Ping Block.*/
> + w5300_write(wp, MR, MR_WDF(1) | MR_PB);
> +
> + /* Setting MAC address */
> + w5300_set_macaddr(wp, dev->dev_addr);
> +
> + /* Setting the size of Rx/Tx FIFO */
> + for (i = 0; i < MAX_SOCK_NUM; ++i) {
> + if (wp->rxbuf_conf[i] > 64) {
> + printk(KERN_ERR "%s: Illegal Channel(%d) RX memory size.\n",
> + DEV_NAME, i);
> + return -EINVAL;
> + }
> + if (wp->txbuf_conf[i] > 64) {
> + printk(KERN_ERR "%s: Illegal Channel(%d) TX memory size.\n",
> + DEV_NAME, i);
> + return -EINVAL;
> + }
> + txbuf_total += wp->txbuf_conf[i];
> + }
> +
> + if (txbuf_total % 8) {
> + printk(KERN_ERR "%s: Illegal memory size register setting.\n",
> + DEV_NAME);
> + return -EINVAL;
> + }
> + w5300_write(wp, RMSR0,
> + (u16) (wp->rxbuf_conf[0] << 8) | (u16) wp->rxbuf_conf[1]);
> + w5300_write(wp, RMSR2,
> + (u16) (wp->rxbuf_conf[2] << 8) | (u16) wp->rxbuf_conf[3]);
> + w5300_write(wp, RMSR4,
> + (u16) (wp->rxbuf_conf[4] << 8) | (u16) wp->rxbuf_conf[5]);
> + w5300_write(wp, RMSR6,
> + (u16) (wp->rxbuf_conf[6] << 8) | (u16) wp->rxbuf_conf[7]);
> + w5300_write(wp, TMSR0,
> + (u16) (wp->txbuf_conf[0] << 8) | (u16) wp->txbuf_conf[1]);
> + w5300_write(wp, TMSR2,
> + (u16) (wp->txbuf_conf[2] << 8) | (u16) wp->txbuf_conf[3]);
> + w5300_write(wp, TMSR4,
> + (u16) (wp->txbuf_conf[4] << 8) | (u16) wp->txbuf_conf[5]);
> + w5300_write(wp, TMSR6,
> + (u16) (wp->txbuf_conf[6] << 8) | (u16) wp->txbuf_conf[7]);
> +
> + /* Setting FIFO Memory Type (TX&RX) */
> + for (i = 0; i < txbuf_total / 8; ++i) {
> + mem_cfg <<= 1;
> + mem_cfg |= 1;
> + }
> + w5300_write(wp, MTYPER, mem_cfg);
> +
> + /* Masking all interrupts */
> + w5300_write(wp, IMR, 0x0000);
> +
> + return 0;
> +}
> +
> +/* Interrupt Handler(ISR) */
> +static irqreturn_t
> +wiz_interrupt(int irq, void *dev_instance)
> +{
> + struct net_device *dev = dev_instance;
> + struct wiz_private *wp = netdev_priv(dev);
> + unsigned long isr, ssr;
> + int s;
> +
> + isr = w5300_read(wp, IR);
> +
> + /* Completing all interrupts at a time. */
> + while (isr) {
> + w5300_write(wp, IR, isr);
> +
> + /* Finding the channel to create the interrupt */
> + s = find_first_bit(&isr, sizeof(u16));
> + ssr = w5300_read(wp, Sn_IR(s));
> + /* socket interrupt is cleared. */
> + w5300_write(wp, Sn_IR(s), ssr);
> + DPRINTK("%s: ISR = %X, SSR = %X, s = %X\n",
> + __func__, isr, ssr, s);
> + if (likely(!s)) {
> + if (ssr & Sn_IR_RECV) {
> + /* De-activation of interrupt */
> + w5300_interrupt_disable(wp, 0);
> + /* Receiving by polling method */
> + napi_schedule(&wp->napi);
> + }
> + }
> +
> + /* Is there any interrupt to be processed? */
> + isr = w5300_read(wp, IR);
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int
> +wiz_open(struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> + int ret;
> +
> + napi_enable(&wp->napi);
> +
> + ret = request_irq(dev->irq, wiz_interrupt,
> + IRQF_IRQPOLL, dev->name, dev);
> + if (ret < 0) {
> + printk(KERN_ERR "%s: request_irq() error!\n", DEV_NAME);
> + return ret;
> + }
> +
> + /* Activating the interrupt of channel 0 that is used for MACRAW. */
> + w5300_interrupt_enable(wp, 0);
> +
> + /* Sending OPEN command to use channel 0 as MACRAW mode. */
> + w5300_open(wp, Sn_MR_MACRAW_MF);
> +
> + netif_start_queue(dev);
> +
> + return 0;
> +}
> +
> +static int
> +wiz_close(struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> +
> + DPRINTK("%s\n", __func__);
> +
> + napi_disable(&wp->napi);
> +
> + /* Interrupt masking of all channels */
> + w5300_write(wp, IMR, 0x0000);
> + netif_stop_queue(dev);
> + w5300_write(wp, Sn_CR(0), Sn_CR_CLOSE);
> + free_irq(dev->irq, dev);
> +
> + return 0;
> +}
> +
> +static int
> +w5300_send_data(struct wiz_private *wp, u8 * buf, ssize_t len)
> +{
> + int i;
> + u16 send_data;
> +
> + /* Writing packets in to Tx FIFO */
> + for (i = 0; i < len; i += 2) {
> + send_data = (buf[i] << 8) | buf[i+1];
> + w5300_write(wp, Sn_TX_FIFO(0), send_data);
> + }
> +
> + w5300_write(wp, Sn_TX_WRSR(0), (u16)(len >> 16));
> + w5300_write(wp, Sn_TX_WRSR2(0), (u16)len);
> + w5300_write(wp, Sn_CR(0), Sn_CR_SEND);
> + while (w5300_read(wp, Sn_CR(0)))
> + udelay(1);
> +
> + return len;
> +}
> +
> +/* Function to transmit data at the MACRAW mode */
> +static int
> +wiz_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> + int ret;
> +
> + DPRINTK("%s: MAC_RAW SEND packet size = %d\n", __func__, skb->len);
> +
> + ret = w5300_send_data(wp, skb->data, skb->len);
> +
> + /* Statistical Process */
> + if (ret < 0) {
> + wp->stats.tx_dropped++;
> + } else {
> + wp->stats.tx_bytes += skb->len;
> + wp->stats.tx_packets++;
> + dev->trans_start = jiffies;
> + }
> + dev_kfree_skb(skb);
> +
> + return 0;
> +}
> +
> +static struct net_device_stats *
> +wiz_get_stats(struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> + DPRINTK("%s: get status\n", __func__);
> + return &wp->stats;
> +}
> +
> +/* It is called when multi-cast list or flag is changed. */
> +static void
> +wiz_set_multicast(struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> +
> + DPRINTK("%s: multicast\n", __func__);
> + if (dev->flags & IFF_PROMISC)
> + w5300_open(wp, Sn_MR_MACRAW);
> + else
> + w5300_open(wp, Sn_MR_MACRAW_MF);
> +}
> +
> +static int
> +wiz_set_mac_address(struct net_device *dev, void *addr)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> + struct sockaddr *sock_addr = addr;
> +
> + DPRINTK("%s: set mac address\n", __func__);
> +
> + spin_lock(&wp->lock);
> + /* Changing MAC address of W5300 */
> + w5300_set_macaddr(wp, sock_addr->sa_data);
> + /* Changing MAC address of material structure to manage W5300 */
> + memcpy(dev->dev_addr, sock_addr->sa_data, dev->addr_len);
> + spin_unlock(&wp->lock);
> +
> + return 0;
> +}
> +
> +static void
> +wiz_tx_timeout(struct net_device *dev)
> +{
> + struct wiz_private *wp = netdev_priv(dev);
> + unsigned long flags;
> +
> + printk(KERN_WARNING "%s: Transmit timeout\n", dev->name);
> +
> + spin_lock_irqsave(&wp->lock, flags);
> + /* Initializing W5300 chip. */
> + w5300_reset(dev);
> + /* Waking up network interface */
> + netif_wake_queue(dev);
> + spin_unlock_irqrestore(&wp->lock, flags);
> +}
> +
> +/*
> + * Polling Function to process only receiving at the MACRAW mode.
> + * De-activating the interrupt when recv interrupt occurs,
> + * and processing the RECEIVE with this Function
> + * Activating the interrupt after completing RECEIVE process
> + * As recv interrupt often occurs at short intervals,
> + * there will system load in case that interrupt handler process the RECEIVE.
> + */
> +static int
> +wiz_rx_poll(struct napi_struct *napi, int budget)
> +{
> + struct sk_buff *skb;
> + struct wiz_private *wp = container_of(napi, struct wiz_private, napi);
> + struct net_device *dev = wp->dev;
> + u16 rxbuf_len, pktlen;
> + u32 crc;
> + int npackets = 0;
> +
> + /* Processing the RECEIVE during Rx FIFO is containing any packet */
> + while (w5300_get_rxsize(wp, 0) > 0) {
> +
> + /* The first 2byte is the information about packet lenth. */
> + w5300_recv_data(wp, 0, (u8 *)&pktlen, 2, 0);
> + DPRINTK("%s: pktlen = %d\n", __func__, pktlen);
> +
> + /*
> + * Allotting the socket buffer in which packet will be contained
> + * Ethernet packet is of 14byte.
> + * In order to make it multiplied by 2, the buffer allocation
> + * should be 2bytes bigger than the packet.
> + */
> + skb = dev_alloc_skb(pktlen + 2);
> + if (!skb) {
> + u8 *temp;
> + printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n",
> + dev->name);
> + temp = kmalloc(pktlen + 4, GFP_KERNEL);
> + wp->stats.rx_dropped++;
> + w5300_recv_data(wp, 0, temp, pktlen + 4, 1);
> + kfree(temp);
> + return -ENOMEM;
> + }
> +
> + /* Initializing the socket buffer */
> + skb->dev = dev;
> + skb_reserve(skb, 2);
> + skb_put(skb, pktlen);
> +
> + /* Reading packets from W5300 Rx FIFO into socket buffer. */
> + w5300_recv_data(wp, 0, (u8 *)skb->data, pktlen, 1);
> +
> + /* Reading and discarding 4byte CRC. */
> + w5300_recv_data(wp, 0, (u8 *)&crc, 4, 0);
> +
> + /* The packet type is Ethernet. */
> + skb->protocol = eth_type_trans(skb, dev);
> +
> + /* Passing packets to uppder stack (kernel). */
> + netif_receive_skb(skb);
> +
> + /* Processing statistical information */
> + wp->stats.rx_packets++;
> + wp->stats.rx_bytes += pktlen;
> + wp->dev->last_rx = jiffies;
> + rxbuf_len -= pktlen;
> + npackets++;
> +
> + if (npackets >= budget)
> + break;
> + }
> +
> + /* If packet number is smaller than budget when getting out of loopback,
> + * the RECEIVE process is completed. */
> + if (npackets < budget) {
> + unsigned long flags;
> + spin_lock_irqsave(&wp->lock, flags);
> + w5300_interrupt_enable(wp, 0);
> + __napi_complete(napi);
> + spin_unlock_irqrestore(&wp->lock, flags);
> + }
> + return npackets;
> +}
> +
> +static const struct net_device_ops wiz_netdev_ops = {
> + .ndo_open = wiz_open,
> + .ndo_stop = wiz_close,
> + .ndo_validate_addr = eth_validate_addr,
> + .ndo_set_mac_address = wiz_set_mac_address,
> + .ndo_set_multicast_list = wiz_set_multicast,
> + .ndo_get_stats = wiz_get_stats,
> + .ndo_start_xmit = wiz_start_xmit,
> + .ndo_tx_timeout = wiz_tx_timeout,
> +};
> +
> +/* Initialize W5300 driver. */
> +static int __devinit
> +w5300_drv_probe(struct platform_device *pdev)
> +{
> + struct net_device *dev;
> + struct wiz_private *wp;
> + struct resource *res;
> + void __iomem *addr;
> + int ret;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + ret = -ENODEV;
> + goto out;
> + }
> +
> + /* Request the chip register regions. */
> + if (!request_mem_region(res->start, SZ_1M, DEV_NAME)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> + /* Allocatting struct net_device structure which is managing W5300 */
> + dev = alloc_etherdev(sizeof(struct wiz_private));
> + if (!dev) {
> + ret = -ENOMEM;
> + goto release_region;
> + }
> +
> + dev->dma = (unsigned char)-1;
> + dev->irq = platform_get_irq(pdev, 0);
> + wp = netdev_priv(dev);
> + wp->dev = dev;
> + addr = ioremap(res->start, SZ_1M);
> + if (!addr) {
> + ret = -ENOMEM;
> + goto release_both;
> + }
> +
> + platform_set_drvdata(pdev, dev);
> + wp->base = addr;
> +
> + spin_lock_init(&wp->lock);
> +
> + /* Initialization of Rx/Tx FIFO size */
> + memcpy(wp->rxbuf_conf, w5300_rxbuf_conf, MAX_SOCK_NUM * sizeof(u8));
> + memcpy(wp->txbuf_conf, w5300_txbuf_conf, MAX_SOCK_NUM * sizeof(u8));
> +
> + dev->base_addr = res->start;
> + dev->addr_len = 6; /* MAC address length. */
> + memcpy(dev->dev_addr, w5300_defmac, dev->addr_len);
> +
> + ether_setup(dev);
> + dev->netdev_ops = &wiz_netdev_ops;
> + /* Setting napi. Enabling to process max 16 packets at a time. */
> + netif_napi_add(dev, &wp->napi, wiz_rx_poll, 16);
> +
> + dev->watchdog_timeo = msecs_to_jiffies(watchdog);
> +
> + strcpy(dev->name, "eth%d");
> +
> + w5300_reset(dev);
> +
> + ret = register_netdev(dev);
> + if (ret != 0) {
> + platform_set_drvdata(pdev, NULL);
> + iounmap(addr);
> +release_both:
> + free_netdev(dev);
> +release_region:
> + release_resource(res);
> + }
> +out:
> + return ret;
> +}
> +
> +static int __devexit
> +w5300_drv_remove(struct platform_device *pdev)
> +{
> + struct net_device *dev = platform_get_drvdata(pdev);
> + struct wiz_private *wp = netdev_priv(dev);
> + struct resource *res;
> +
> + platform_set_drvdata(pdev, NULL);
> + unregister_netdev(dev);
> +
> + if (wp->base != NULL)
> + iounmap(wp->base);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (res != NULL)
> + release_resource(res);
> +
> + free_netdev(dev);
> +
> + return 0;
> +}
> +
> +static int
> +w5300_drv_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + struct net_device *dev = platform_get_drvdata(pdev);
> +
> + if (dev) {
> + struct wiz_private *wp = netdev_priv(dev);
> +
> + if (netif_running(dev)) {
> + netif_device_detach(dev);
> + w5300_write(wp, IMR, 0x0000);
> + w5300_write(wp, Sn_CR(0), Sn_CR_CLOSE);
> + }
> + }
> + return 0;
> +}
> +
> +static int
> +w5300_drv_resume(struct platform_device *pdev)
> +{
> + struct net_device *dev = platform_get_drvdata(pdev);
> +
> + if (dev) {
> + struct wiz_private *wp = netdev_priv(dev);
> +
> + if (netif_running(dev)) {
> + w5300_reset(dev);
> + w5300_interrupt_enable(wp, 0);
> + w5300_open(wp, Sn_MR_MACRAW_MF);
> + netif_device_attach(dev);
> + }
> + }
> +
> + return 0;
> +}
> +
> +static struct platform_driver w5300_driver = {
> + .probe = w5300_drv_probe,
> + .remove = __devexit_p(w5300_drv_remove),
> + .suspend = w5300_drv_suspend,
> + .resume = w5300_drv_resume,
> + .driver = {
> + .name = DEV_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +static int __init
> +wiz_module_init(void)
> +{
> + return platform_driver_register(&w5300_driver);
> +}
> +
> +static void __exit
> +wiz_module_exit(void)
> +{
> + platform_driver_unregister(&w5300_driver);
> +}
> +
> +module_init(wiz_module_init);
> +module_exit(wiz_module_exit);
> diff --git a/drivers/net/w5300.h b/drivers/net/w5300.h
> new file mode 100644
> index 0000000..d8583be
> --- /dev/null
> +++ b/drivers/net/w5300.h
> @@ -0,0 +1,350 @@
> +#ifndef _W5300_H_
> +#define _W5300_H_
> +
> +/* Maximum socket number. W5300 supports max 8 channels. */
> +#define MAX_SOCK_NUM 8
> +#ifdef W5300_DEBUG
> +#define DPRINTK(format, args...) printk(format, ##args)
> +#else
> +#define DPRINTK(format, args...)
> +#endif
> +
> +/* socket register */
> +#define CH_BASE (0x200)
> +
> +/* size of each channel register map */
> +#define CH_SIZE 0x40
> +
> +/* Mode Register address */
> +#define MR (0)
> +#define MR1 (MR + 1)
> +
> +#define IDM_AR (0x02)
> +#define IDM_AR1 (IDM_AR + 1)
> +
> +#define IDM_DR (0x04)
> +#define IDM_DR1 (IDM_DR + 1)
> +
> +/* Interrupt Register */
> +#define IR (0x02)
> +#define IR1 (IR + 1);
> +
> +/* Interrupt mask register */
> +#define IMR (0x04)
> +#define IMR1 (IMR + 1)
> +
> +/* Interrupt mask register */
> +#define STAR (0x06)
> +#define STAR1 (STAR + 1)
> +
> +/* Source MAC Register address */
> +#define SHAR (0x08)
> +#define SHAR1 (SHAR + 1)
> +#define SHAR2 (SHAR + 2)
> +#define SHAR3 (SHAR + 3)
> +#define SHAR4 (SHAR + 4)
> +#define SHAR5 (SHAR + 5)
> +
> +/* Gateway IP Register address */
> +#define GAR (0x10)
> +#define GAR1 (GAR + 1)
> +#define GAR2 (GAR + 2)
> +#define GAR3 (GAR + 3)
> +
> +/* Subnet mask Register address */
> +#define SUBR (0x14)
> +#define SUBR1 (SUBR + 1)
> +#define SUBR2 (SUBR + 2)
> +#define SUBR3 (SUBR + 3)
> +
> +/* Source IP Register address */
> +#define SIPR (0x18)
> +#define SIPR1 (SIPR + 1)
> +#define SIPR2 (SIPR + 2)
> +#define SIPR3 (SIPR + 3)
> +
> +/* Timeout register address(1 is 100us) */
> +#define RTR (0x1C)
> +#define RTR1 (RTR + 1)
> +
> +/* Retry count reigster */
> +#define RCR (0x1E)
> +#define RCR1 (RCR + 1)
> +
> +/* Transmit memory size reigster */
> +#define TMSR0 (0x20)
> +#define TMSR1 (TMSR0 + 1)
> +#define TMSR2 (TMSR0 + 2)
> +#define TMSR3 (TMSR0 + 3)
> +#define TMSR4 (TMSR0 + 4)
> +#define TMSR5 (TMSR0 + 5)
> +#define TMSR6 (TMSR0 + 6)
> +#define TMSR7 (TMSR0 + 7)
> +
> +#define TMSR_01 (0x20)
> +#define TMSR_23 (TMSR_01 + 2)
> +#define TMSR_45 (TMSR_01 + 4)
> +#define TMSR_67 (TMSR_01 + 6)
> +
> +/* Receive memory size reigster */
> +#define RMSR0 (0x28)
> +#define RMSR1 (RMSR0 + 1)
> +#define RMSR2 (RMSR0 + 2)
> +#define RMSR3 (RMSR0 + 3)
> +#define RMSR4 (RMSR0 + 4)
> +#define RMSR5 (RMSR0 + 5)
> +#define RMSR6 (RMSR0 + 6)
> +#define RMSR7 (RMSR0 + 7)
> +
> +#define RMSR_01 (0x28)
> +#define RMSR_23 (RMSR_01 + 2)
> +#define RMSR_45 (RMSR_01 + 4)
> +#define RMSR_67 (RMSR_01 + 6)
> +
> +/* Memory Type Register
> + * '1' - TX memory
> + * '0' - RX memory */
> +#define MTYPER (0x30)
> +#define MYYPER1 (MTYPER + 1)
> +
> +/* Authentication type register address in PPPoE mode */
> +#define PATR (0x32)
> +#define PATR1 (PATR + 1)
> +
> +#define PTIMER (0x36)
> +#define PTIMER1 (PTIMER + 1)
> +
> +#define PMAGIC (0x38)
> +#define PMAGIC1 (PMAGIC + 1)
> +
> +/* PPPoE session ID register */
> +#define PSIDR (0x3C)
> +#define PSIDR1 (PSIDR + 1)
> +
> +/* PPPoE destination hardware address register */
> +#define PDHAR (0x40)
> +#define PDHAR0 PDHAR
> +#define PDHAR1 (PDHAR + 1)
> +#define PDHAR2 (PDHAR + 2)
> +#define PDHAR3 (PDHAR + 3)
> +#define PDHAR4 (PDHAR + 4)
> +#define PDHAR5 (PDHAR + 5)
> +
> +/* Unreachable IP register address in UDP mode */
> +#define UIPR (0x48)
> +#define UIPR1 (UIPR + 1)
> +#define UIPR2 (UIPR + 2)
> +#define UIPR3 (UIPR + 3)
> +
> +/* Unreachable Port register address in UDP mode */
> +#define UPORT (0x4C)
> +#define UPORT1 (UPORT + 1)
> +
> +/* Fragment register */
> +#define FMTUR (0x4E)
> +#define FMTUR1 (FMTUR + 1)
> +
> +/* PIN 'BRDYn' configure register */
> +#define Pn_BRDYR(n) (0x60 + n*4)
> +#define Pn_BRDYR1(n) (Pn_BRDYR(n) + 1)
> +
> +/* PIN 'BRDYn' buffer depth register */
> +#define Pn_BDPTHR(n) (0x62 + n*4)
> +#define Pn_BDPTHR1(n) (Pn_BDPTHR(n) + 1)
> +
> +/* Chip ID register(=0x5300) */
> +#define IDR (0xFE)
> +#define IDR1 (IDR + 1)
> +
> +/* socket Mode register */
> +#define Sn_MR(ch) (CH_BASE + ch * CH_SIZE + 0x00)
> +#define Sn_MR1(ch) (Sn_MR(ch)+1)
> +
> +/* socket command register */
> +#define Sn_CR(ch) (CH_BASE + ch * CH_SIZE + 0x02)
> +#define Sn_CR1(ch) (Sn_CR(ch)+1);
> +
> +/* socket interrupt mask register */
> +#define Sn_IMR(ch) (CH_BASE + ch * CH_SIZE + 0x04)
> +#define Sn_IMR1(ch) (Sn_IMR(ch)+1)
> +
> +/* socket interrupt register */
> +#define Sn_IR(ch) (CH_BASE + ch * CH_SIZE + 0x06)
> +#define Sn_IR1(ch) (Sn_IR(ch)+1)
> +
> +/* socket status register */
> +#define Sn_SSR(ch) (CH_BASE + ch * CH_SIZE + 0x08)
> +#define Sn_SSR1(ch) (Sn_SSR(ch)+1);
> +
> +/* source port register */
> +#define Sn_PORTR(ch) (CH_BASE + ch * CH_SIZE + 0x0A)
> +#define Sn_PORTR1(ch) (Sn_PORTR(ch)+1)
> +
> +/* Peer MAC register address */
> +#define Sn_DHAR(ch) (CH_BASE + ch * CH_SIZE + 0x0C)
> +#define Sn_DHAR1(ch) (Sn_DHAR(ch)+1)
> +#define Sn_DHAR2(ch) (Sn_DHAR(ch)+2)
> +#define Sn_DHAR3(ch) (Sn_DHAR(ch)+3)
> +#define Sn_DHAR4(ch) (Sn_DHAR(ch)+4)
> +#define Sn_DHAR5(ch) (Sn_DHAR(ch)+5)
> +
> +/* Peer port register address */
> +#define Sn_DPORTR(ch) (CH_BASE + ch * CH_SIZE + 0x12)
> +#define Sn_DPORTR1(ch) (Sn_DPORTR(ch)+1)
> +
> +/* Peer IP register address */
> +#define Sn_DIPR(ch) (CH_BASE + ch * CH_SIZE + 0x14)
> +#define Sn_DIPR1(ch) (Sn_DIPR(ch)+1)
> +#define Sn_DIPR2(ch) (Sn_DIPR(ch)+2)
> +#define Sn_DIPR3(ch) (Sn_DIPR(ch)+3)
> +
> +/* Maximum Segment Size(Sn_MSSR0) register address */
> +#define Sn_MSSR(ch) (CH_BASE + ch * CH_SIZE + 0x18)
> +#define Sn_MSSR1(ch) (Sn_MSSR(ch)+1)
> +
> +/* Protocol of IP Header field register in IP raw mode */
> +#define Sn_PROTOR(ch) (CH_BASE + ch * CH_SIZE + 0x1A)
> +#define Sn_PROTOR1(ch) (Sn_PROTOR(ch)+1)
> +
> +/* Socket keep alive timer register */
> +#define Sn_KPALVTR(ch) Sn_PROTOR(ch)
> +
> +/* IP Type of Service(TOS) Register */
> +#define Sn_TOSR(ch) (CH_BASE + ch * CH_SIZE + 0x1C)
> +#define Sn_TOSR1(ch) (Sn_TOSR(ch)+1)
> +
> +/* IP Time to live(TTL) Register */
> +#define Sn_TTLR(ch) (CH_BASE + ch * CH_SIZE + 0x1E)
> +#define Sn_TTLR1(ch) (Sn_TTLR(ch)+1)
> +
> +/* Transmit Size Register (Byte count) */
> +#define Sn_TX_WRSR(ch) (CH_BASE + ch * CH_SIZE + 0x20)
> +#define Sn_TX_WRSR1(ch) (Sn_TX_WRSR(ch) + 1)
> +#define Sn_TX_WRSR2(ch) (Sn_TX_WRSR(ch) + 2)
> +#define Sn_TX_WRSR3(ch) (Sn_TX_WRSR(ch) + 3)
> +
> +/* Transmit free memory size register (Byte count) */
> +#define Sn_TX_FSR(ch) (CH_BASE + ch * CH_SIZE + 0x24)
> +#define Sn_TX_FSR1(ch) (Sn_TX_FSR(ch) + 1)
> +#define Sn_TX_FSR2(ch) (Sn_TX_FSR(ch) + 2)
> +#define Sn_TX_FSR3(ch) (Sn_TX_FSR(ch) + 3)
> +
> +/* Received data size register (Byte count) */
> +#define Sn_RX_RSR(ch) (CH_BASE + ch * CH_SIZE + 0x28)
> +#define Sn_RX_RSR1(ch) (Sn_RX_RSR(ch) + 1)
> +#define Sn_RX_RSR2(ch) (Sn_RX_RSR(ch) + 2)
> +#define Sn_RX_RSR3(ch) (Sn_RX_RSR(ch) + 3)
> +
> +/* Socket fragment register */
> +#define Sn_FRAGR(ch) (CH_BASE + ch * CH_SIZE + 0x2C)
> +#define Sn_FRAGR1(ch) (Sn_FRAGR(ch) + 1)
> +
> +/* FIFO register for Transmit */
> +#define Sn_TX_FIFO(ch) (CH_BASE + ch * CH_SIZE + 0x2E)
> +#define Sn_TX_FIFO1(ch) (Sn_TX_FIFO(ch) + 1)
> +
> +/* FIFO register for Receive */
> +#define Sn_RX_FIFO(ch) (CH_BASE + ch * CH_SIZE + 0x30)
> +#define Sn_RX_FIFO1(ch) (Sn_RX_FIFO(ch) + 1)
> +
> +/* MODE register values */
> +#define MR_DBW (1 << 15) /**< Data bus width bit of MR. */
> +#define MR_MPF (1 << 14) /**< Mac layer pause frame bit of MR. */
> +#define MR_WDF(x) ((x & 0x07) << 11) /**< Write data fetch time bit of MR. */
> +#define MR_RDH (1 << 10) /**< Read data hold time bit of MR. */
> +#define MR_FS (1 << 8) /**< FIFO swap bit of MR. */
> +#define MR_RST (1 << 7) /**< S/W reset bit of MR. */
> +#define MR_MT (1 << 5) /**< Memory test bit of MR. */
> +#define MR_PB (1 << 4) /**< Ping block bit of MR. */
> +#define MR_PPPoE (1 << 3) /**< PPPoE bit of MR. */
> +#define MR_DBS (1 << 2) /**< Data bus swap of MR. */
> +#define MR_IND (1 << 0) /**< Indirect mode bit of MR. */
> +
> +/* IR register values */
> +#define IR_IPCF (1 << 7) /**< IP conflict bit of IR. */
> +#define IR_DPUR (1 << 6) /**< Destination port unreachable bit of IR. */
> +#define IR_PPPT (1 << 5) /**< PPPoE terminate bit of IR. */
> +#define IR_FMTU (1 << 4) /**< Fragment MTU bit of IR. */
> +#define IR_SnINT(n) (0x01 << n) /**< SOCKETn interrupt occurrence bit of IR. */
> +
> +/* Pn_BRDYR values */
> +#define Pn_PEN (1 << 7) /**< PIN 'BRDYn' enable bit of Pn_BRDYR. */
> +#define Pn_MT (1 << 6) /**< PIN memory type bit of Pn_BRDYR. */
> +#define Pn_PPL (1 << 5) /**< PIN Polarity bit of Pn_BRDYR. */
> +#define Pn_SN(n) ((n & 0x07) << 0) /**< PIN Polarity bit of Pn_BRDYR. */
> +
> +/* Sn_MR values */
> +#define Sn_MR_ALIGN (1 << 8) /**< Alignment bit of Sn_MR. */
> +#define Sn_MR_MULTI (1 << 7) /**< Multicasting bit of Sn_MR. */
> +#define Sn_MR_MF (1 << 6) /**< MAC filter bit of Sn_MR. */
> +#define Sn_MR_IGMPv (1 << 5) /**< IGMP version bit of Sn_MR. */
> +#define Sn_MR_ND (1 << 5) /**< No delayed ack bit of Sn_MR. */
> +#define Sn_MR_CLOSE 0x00 /**< Protocol bits of Sn_MR. */
> +#define Sn_MR_TCP 0x01 /**< Protocol bits of Sn_MR. */
> +#define Sn_MR_UDP 0x02 /**< Protocol bits of Sn_MR. */
> +#define Sn_MR_IPRAW 0x03 /**< Protocol bits of Sn_MR. */
> +#define Sn_MR_MACRAW 0x04 /**< Protocol bits of Sn_MR. */
> +#define Sn_MR_MACRAW_MF 0x44 /**< Protocol bits of Sn_MR */
> +#define Sn_MR_PPPoE 0x05 /**< Protocol bits of Sn_MR. */
> +
> +/* Sn_CR values */
> +#define Sn_CR_OPEN 0x01 /**< OPEN command value of Sn_CR. */
> +#define Sn_CR_LISTEN 0x02 /**< LISTEN command value of Sn_CR. */
> +#define Sn_CR_CONNECT 0x04 /**< CONNECT command value of Sn_CR. */
> +#define Sn_CR_DISCON 0x08 /**< DISCONNECT command value of Sn_CR. */
> +#define Sn_CR_CLOSE 0x10 /**< CLOSE command value of Sn_CR. */
> +#define Sn_CR_SEND 0x20 /**< SEND command value of Sn_CR. */
> +#define Sn_CR_SEND_MAC 0x21 /**< SEND_MAC command value of Sn_CR. */
> +#define Sn_CR_SEND_KEEP 0x22 /**< SEND_KEEP command value of Sn_CR */
> +#define Sn_CR_RECV 0x40 /**< RECV command value of Sn_CR */
> +#define Sn_CR_PCON 0x23 /**< PCON command value of Sn_CR */
> +#define Sn_CR_PDISCON 0x24 /**< PDISCON command value of Sn_CR */
> +#define Sn_CR_PCR 0x25 /**< PCR command value of Sn_CR */
> +#define Sn_CR_PCN 0x26 /**< PCN command value of Sn_CR */
> +#define Sn_CR_PCJ 0x27 /**< PCJ command value of Sn_CR */
> +
> +/* Sn_IR values */
> +#define Sn_IR_PRECV 0x80 /**< PPP receive bit of Sn_IR */
> +#define Sn_IR_PFAIL 0x40 /**< PPP fail bit of Sn_IR */
> +#define Sn_IR_PNEXT 0x20 /**< PPP next phase bit of Sn_IR */
> +#define Sn_IR_SENDOK 0x10 /**< Send OK bit of Sn_IR */
> +#define Sn_IR_TIMEOUT 0x08 /**< Timout bit of Sn_IR */
> +#define Sn_IR_RECV 0x04 /**< Receive bit of Sn_IR */
> +#define Sn_IR_DISCON 0x02 /**< Disconnect bit of Sn_IR */
> +#define Sn_IR_CON 0x01 /**< Connect bit of Sn_IR */
> +
> +/* Sn_SSR values */
> +#define SOCK_CLOSED 0x00 /**< SOCKETn is released */
> +#define SOCK_ARP 0x01 /**< ARP-request is transmitted in order to acquire destination hardware address. */
> +#define SOCK_INIT 0x13 /**< SOCKETn is open as TCP mode. */
> +#define SOCK_LISTEN 0x14 /**< SOCKETn operates as "TCP SERVER" and waits for connection-request (SYN packet) from "TCP CLIENT". */
> +#define SOCK_SYNSENT 0x15 /**< Connect-request(SYN packet) is transmitted to "TCP SERVER". */
> +#define SOCK_SYNRECV 0x16 /**< Connect-request(SYN packet) is received from "TCP CLIENT". */
> +#define SOCK_ESTABLISHED 0x17 /**< TCP connection is established. */
> +#define SOCK_FIN_WAIT 0x18 /**< SOCKETn is closing. */
> +#define SOCK_CLOSING 0x1A /**< SOCKETn is closing. */
> +#define SOCK_TIME_WAIT 0x1B /**< SOCKETn is closing. */
> +#define SOCK_CLOSE_WAIT 0x1C /**< Disconnect-request(FIN packet) is received from the peer. */
> +#define SOCK_LAST_ACK 0x1D /**< SOCKETn is closing. */
> +#define SOCK_UDP 0x22 /**< SOCKETn is open as UDP mode. */
> +#define SOCK_IPRAW 0x32 /**< SOCKETn is open as IPRAW mode. */
> +#define SOCK_MACRAW 0x42 /**< SOCKET0 is open as MACRAW mode. */
> +#define SOCK_PPPoE 0x5F /**< SOCKET0 is open as PPPoE mode. */
> +
> +/* IP PROTOCOL */
> +#define IPPROTO_IP 0 /* Dummy for IP */
> +#define IPPROTO_ICMP 1 /* Control message protocol */
> +#define IPPROTO_IGMP 2 /* Internet group management protocol */
> +#define IPPROTO_GGP 3 /* Gateway^2 (deprecated) */
> +#define IPPROTO_TCP 6 /* TCP */
> +#define IPPROTO_PUP 12 /* PUP */
> +#define IPPROTO_UDP 17 /* UDP */
> +#define IPPROTO_IDP 22 /* XNS idp */
> +#define IPPROTO_ND 77 /* UNOFFICIAL net disk protocol */
> +#define IPPROTO_RAW 255 /* Raw IP packet */
> +
> +/* W5300 Register READ/WRITE funtions(Just 16 bit interface). */
> +#define w5300_write(wp, addr, val) writew(val, (wp->base + addr))
> +#define w5300_read(wp, addr) readw((wp->base + addr))
> +
> +#endif /* _W5300_H_ */
> --
> 1.7.1
>
>
Hi.
Please check this patch. Not only it had been finished testing, but
also confirmed by WIZnet(http://wiznet.co.kr).
If any problems, please let me know.
Best Regards,
Taehun Kim.
^ permalink raw reply
* [PATCH] net: fix a typo in Documentation/networking/scaling.txt
From: Jason Wang @ 2011-09-27 10:03 UTC (permalink / raw)
To: netdev, davem, linux-kernel; +Cc: rdunlap, linux-doc
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Documentation/networking/scaling.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt
index 58fd741..8ce7c30 100644
--- a/Documentation/networking/scaling.txt
+++ b/Documentation/networking/scaling.txt
@@ -243,7 +243,7 @@ configured. The number of entries in the global flow table is set through:
The number of entries in the per-queue flow table are set through:
- /sys/class/net/<dev>/queues/tx-<n>/rps_flow_cnt
+ /sys/class/net/<dev>/queues/rx-<n>/rps_flow_cnt
== Suggested Configuration
^ permalink raw reply related
* Re: [PATCH v3 1/7] Basic kernel memory functionality for the Memory Controller
From: Balbir Singh @ 2011-09-27 10:06 UTC (permalink / raw)
To: Glauber Costa
Cc: linux-kernel, paul, lizf, kamezawa.hiroyu, ebiederm, davem,
gthelen, netdev, linux-mm, kirill, Ying Han
In-Reply-To: <4E7DECA0.5020707@parallels.com>
>> I know we have a lot of pending xxx_from_cont() and struct cgroup
>> *cont, can we move it to memcg notation to be more consistent with our
>> usage. There is a patch to convert old usage
>>
>
> Hello Balbir, I missed this comment. What exactly do you propose in this
> patch, since I have to assume that the patch you talk about is not applied?
> Is it just a change to the parameter name that you propose?
>
Yes, it is a patch posted on linux-mm by raghavendra
Balbir Singh
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* ioctl interface for ethernet switch configuration
From: N, Mugunthan V @ 2011-09-27 10:06 UTC (permalink / raw)
To: netdev@vger.kernel.org
Hi All
I am implementing a network driver for a 3 port Ethernet switch. We have sorted out the data path for the switch driver. Additionally being a switch module, there are lot other configuration options to program the ALE entries and configure forwarding rules. We are considering implementing these through driver ioctl interface. Are there existing drivers that implement these? Is there a standard interface to handle such a requirement?
---
Regards,
Mugunthan V N.
^ permalink raw reply
* [PATCH v2] net/flow: Fix potential memory leak
From: Huajun Li @ 2011-09-27 10:34 UTC (permalink / raw)
To: David Miller; +Cc: Eric Dumazet, netdev, Huajun Li
While preparing net flow caches, once fail may cause potential memory
leak , fix it.
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Huajun Li <huajun.li.lee@gmail.com>
---
net/core/flow.c | 16 +++++++++++++++-
1 files changed, 15 insertions(+), 1 deletions(-)
diff --git a/net/core/flow.c b/net/core/flow.c
index 555a456..4e60fce 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -413,7 +413,7 @@ static int __init flow_cache_init(struct flow_cache *fc)
for_each_online_cpu(i) {
if (flow_cache_cpu_prepare(fc, i))
- return -ENOMEM;
+ goto err;
}
fc->hotcpu_notifier = (struct notifier_block){
.notifier_call = flow_cache_cpu,
@@ -426,6 +426,20 @@ static int __init flow_cache_init(struct flow_cache *fc)
add_timer(&fc->rnd_timer);
return 0;
+
+err:
+ for_each_possible_cpu(i) {
+ struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i);
+ kfree(fcp->hash_table);
+ fcp->hash_table = NULL;
+ }
+
+ if (fc->percpu) {
+ free_percpu(fc->percpu);
+ fc->percpu = NULL;
+ }
+
+ return -ENOMEM;
}
static int __init flow_cache_init_global(void)
--
1.7.4.1
^ permalink raw reply related
* [PATCH net-next 1/2] be2net: fix multicast filter programming Multicast programming has been broken since commit 5b8821b7. Setting the MULTICAST flag while sending the cmd to the FW was missing. Fixed this.
From: Sathya Perla @ 2011-09-27 11:13 UTC (permalink / raw)
To: netdev
Also fixed-up some indentation in the adjacent lines.
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be_cmds.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index bebeee6..6bc07c7 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1580,14 +1580,16 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
BE_IF_FLAGS_VLAN_PROMISCUOUS);
if (value == ON)
req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS |
- BE_IF_FLAGS_VLAN_PROMISCUOUS);
+ BE_IF_FLAGS_VLAN_PROMISCUOUS);
} else if (flags & IFF_ALLMULTI) {
req->if_flags_mask = req->if_flags =
- cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+ cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
} else {
struct netdev_hw_addr *ha;
int i = 0;
+ req->if_flags_mask = req->if_flags =
+ cpu_to_le32(BE_IF_FLAGS_MULTICAST);
req->mcast_num = cpu_to_le16(netdev_mc_count(adapter->netdev));
netdev_for_each_mc_addr(ha, adapter->netdev)
memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
--
1.7.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