Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] ax25: Fix possible oops in ax25_make_new
From: David Miller @ 2009-09-30 23:44 UTC (permalink / raw)
  To: jarkao2; +Cc: ralf, f6bvp, bernard.pidoux, netdev, linux-hams
In-Reply-To: <20090927205701.GA7205@del.dom.local>

From: Jarek Poplawski <jarkao2@gmail.com>
Date: Sun, 27 Sep 2009 22:57:02 +0200

> In ax25_make_new, if kmemdup of digipeat returns an error, there would
> be an oops in sk_free while calling sk_destruct, because sk_protinfo
> is NULL at the moment; move sk->sk_destruct initialization after this.
> 
> BTW of reported-by: Bernard Pidoux F6BVP <f6bvp@free.fr>
> 
> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>

Applied and queued up for -stable, thanks!

^ permalink raw reply

* Re: [PATCH] net: restore tx timestamping for accelerated vlans
From: David Miller @ 2009-09-30 23:43 UTC (permalink / raw)
  To: eric.dumazet; +Cc: kaber, netdev
In-Reply-To: <4AC20441.8040004@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 29 Sep 2009 14:57:37 +0200

> Since commit 9b22ea560957de1484e6b3e8538f7eef202e3596
> ( net: fix packet socket delivery in rx irq handler )
> 
> We lost rx timestamping of packets received on accelerated vlans.
> 
> Effect is that tcpdump on real dev can show strange timings, since it gets rx timestamps
> too late (ie at skb dequeueing time, not at skb queueing time)
 ...
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied, and queued up for -stable, thanks!

^ permalink raw reply

* Re: [PATCH] Phonet: fix mutex imbalance
From: David Miller @ 2009-09-30 23:41 UTC (permalink / raw)
  To: remi; +Cc: netdev, remi.denis-courmont
In-Reply-To: <1254208599-1274-1-git-send-email-remi@remlab.net>

From: Rémi Denis-Courmont <remi@remlab.net>
Date: Tue, 29 Sep 2009 10:16:39 +0300

> From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
> 
> port_mutex was unlocked twice.
> 
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>

Applied, thanks!

^ permalink raw reply

* Re: [PATCH] sit: fix off-by-one in ipip6_tunnel_get_prl
From: David Miller @ 2009-09-30 23:40 UTC (permalink / raw)
  To: contact; +Cc: netdev, fred.l.templin
In-Reply-To: <1254259625-29320-1-git-send-email-contact@saschahlusiak.de>

From: Sascha Hlusiak <contact@saschahlusiak.de>
Date: Tue, 29 Sep 2009 23:27:05 +0200

> When requesting all prl entries (kprl.addr == INADDR_ANY) and there are
> more prl entries than there is space passed from userspace, the existing
> code would always copy cmax+1 entries, which is more than can be handled.
> 
> This patch makes the kernel copy only exactly cmax entries.
> 
> Signed-off-by: Sascha Hlusiak <contact@saschahlusiak.de>
> Acked-By: Fred L. Templin <Fred.L.Templin@boeing.com>

Applied and queued up for -stable, thanks.

^ permalink raw reply

* Re: [PATCH net-next-2.6] be2net: Workaround to fix a bug in Rx Completion processing.
From: David Miller @ 2009-09-30 23:37 UTC (permalink / raw)
  To: ajitk; +Cc: netdev
In-Reply-To: <20090930090656.GA5215@serverengines.com>

From: Ajit Khaparde <ajitk@serverengines.com>
Date: Wed, 30 Sep 2009 14:37:06 +0530

> vtp bit in RX completion descriptor could be wrongly set in
> some skews of BladEngine.  Ignore this  bit if vtm is not set.
> This patch is against the net-next-2.6 tree.
> 
> Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>

This doesn't apply.

Until I start taking new feature patches, net-next-2.6 is just
going to be a stale GIT tree based upon Linus's tree at some
point in time long ago.

net-2.6 is far in front of that, and actually since this is a bug
fix you really should be sending me this patch against that.

^ permalink raw reply

* Re: [PATCH] net: fix NOHZ: local_softirq_pending 08
From: David Miller @ 2009-09-30 23:33 UTC (permalink / raw)
  To: oliver-fJ+pQTUTwRTk1uMJSBkQmQ
  Cc: johannes-cdvu00un1VgdHxzADdlk8Q, mb-fseUSCV1ubazQB+pC5nmwQ,
	kalle.valo-X3B1VOXEql0, linville-2XuSBdqkA4R54TAoqtyWWQ,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <4AC3A0F1.3060306-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>

From: Oliver Hartkopp <oliver-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>
Date: Wed, 30 Sep 2009 20:18:25 +0200

> Socket buffers that are generated and received inside softirqs or from process
> context must not use netif_rx() that's intended to be used from irq context only.
> 
> This patch introduces a new helper function netif_rx_ti(skb) that tests for
> in_interrupt() before invoking netif_rx() or netif_rx_ni().
> 
> It fixes the ratelimited kernel warning
> 
>         NOHZ: local_softirq_pending 08
> 
> in the mac80211 and can subsystems.
> 
> Signed-off-by: Oliver Hartkopp <oliver-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>

I bet all of these code paths can use netif_receive_skb() or
don't need this conditional blob at all.

Looking at some specific cases in this patch:

1) VCAN:  This RX routine is only invoked from the drivers
   ->ndo_start_xmit() handler, and therefore like the loopback
   driver we know that BH's are already disabled and therefore
   it can always use netif_rx() safely.

   Why did you convert this case?

   And if this needs to be converted, why doesn't loopback need
   to be?

2) af_can.c:  In what situation will netif_rx_ni() not be appropriate
   here?  It should always execute in softirq or user context, now
   hardirq context.

And the list goes on and on, I don't really like this new conditional
testing of interrupt state.  As always, that's usually a red flag and
as far as I can see these spots where you're changing things are only
trying to receive packets in one of the two possible cases not both.

I'm not applying this until all of these details are sorted out and
you add some verbosity to the commit message explaining each and every
case you are changing, what contexts those cases can be called
from, and from where.

Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] net: Fix sock_wfree() race
From: David Miller @ 2009-09-30 23:23 UTC (permalink / raw)
  To: eric.dumazet; +Cc: jarkao2, albcamus, parag.lkml, linux-kernel, netdev
In-Reply-To: <4ABBDB54.4000609@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 24 Sep 2009 22:49:24 +0200

> [PATCH] net: Fix sock_wfree() race
> 
> Commit 2b85a34e911bf483c27cfdd124aeb1605145dc80
> (net: No more expensive sock_hold()/sock_put() on each tx)
> opens a window in sock_wfree() where another cpu
> might free the socket we are working on.
> 
> A fix is to call sk->sk_write_space(sk) while still
> holding a reference on sk.
> 
> 
> Reported-by: Jike Song <albcamus@gmail.com>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied to net-2.6 and I'll queue this up for -stable.

Thanks!

^ permalink raw reply

* Re: [PATCH,TRIVIAL] Fix csum_ipv6_magic asm memory clobber
From: David Miller @ 2009-09-30 23:22 UTC (permalink / raw)
  To: akpm; +Cc: samuel.thibault, hpa, linux-kernel, mingo, tglx, andi, netdev
In-Reply-To: <20090930161939.8c6d140a.akpm@linux-foundation.org>

From: Andrew Morton <akpm@linux-foundation.org>
Date: Wed, 30 Sep 2009 16:19:39 -0700

> From: Samuel Thibault <samuel.thibault@ens-lyon.org>
> 
> Just like ip_fast_csum, the assembly snippet in csum_ipv6_magic needs a
> memory clobber, as it is only passed the address of the buffer, not a
> memory reference to the buffer itself.
> 
> This caused failures in Hurd's pfinetv4 when we tried to compile it with
> gcc-4.3 (bogus checksums).
> 
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

I'm happy to see this go in via the x86 tree, and thus:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [PATCH,TRIVIAL] Fix csum_ipv6_magic asm memory clobber
From: Andrew Morton @ 2009-09-30 23:19 UTC (permalink / raw)
  To: Samuel Thibault; +Cc: hpa, linux-kernel, mingo, tglx, davem, andi, netdev
In-Reply-To: <20090930230138.GZ6451@const.famille.thibault.fr>

On Thu, 1 Oct 2009 01:01:38 +0200
Samuel Thibault <samuel.thibault@ens-lyon.org> wrote:

> Actually it hit Hurd's pfinetv4 when we tried to compile it with
> gcc-4.3 (bogus checksums).

That's important information!  I updated the changelog and added the
Cc:stable, thanks.


Full patch for netdev benefit:


From: Samuel Thibault <samuel.thibault@ens-lyon.org>

Just like ip_fast_csum, the assembly snippet in csum_ipv6_magic needs a
memory clobber, as it is only passed the address of the buffer, not a
memory reference to the buffer itself.

This caused failures in Hurd's pfinetv4 when we tried to compile it with
gcc-4.3 (bogus checksums).

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 arch/x86/include/asm/checksum_32.h |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff -puN arch/x86/include/asm/checksum_32.h~x86-fix-csum_ipv6_magic-asm-memory-clobber arch/x86/include/asm/checksum_32.h
--- a/arch/x86/include/asm/checksum_32.h~x86-fix-csum_ipv6_magic-asm-memory-clobber
+++ a/arch/x86/include/asm/checksum_32.h
@@ -161,7 +161,8 @@ static inline __sum16 csum_ipv6_magic(co
 	    "adcl $0, %0	;\n"
 	    : "=&r" (sum)
 	    : "r" (saddr), "r" (daddr),
-	      "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+	      "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
+	    : "memory");
 
 	return csum_fold(sum);
 }
_


^ permalink raw reply

* capi.c calls receive_buf with interrupts disabled (was: N_PPP_SYNC ldisc BUG: sleeping function called from invalid context)
From: Tilman Schmidt @ 2009-09-30 23:15 UTC (permalink / raw)
  To: Jarek Poplawski
  Cc: Alan Cox, linux-kernel, netdev, Alan Cox, Michael Buesch,
	isdn4linux
In-Reply-To: <4AC3C9B8.9080003@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2709 bytes --]

Jarek Poplawski schrieb:
> Tilman Schmidt wrote, On 09/30/2009 08:55 PM:
[...]
>> - ppp_sync_receive() was called, as the LD's receive_buf method,
>>   via handle_recv_skb() [drivers/isdn/capi/capi.c line 504, inlined]
>>   from handle_minor_recv() [drivers/isdn/capi/capi.c line 519]
>>
>> - handle_minor_recv() was called from capi_recv_message()
>>   [drivers/isdn/capi/capi.c line 656]
>>
>> - capi_recv_message() was called, as the CAPI application's
>>   recv_message method, from recv_handler()
>>   [drivers/isdn/capi/kcapi.c line 268]
>>
>> - recv_handler() is never called directly. It's only scheduled
>>   via the work queue ap->recv_work from capi_ctr_handle_message()
>>   [drivers/isdn/capi/kcapi.c line 349]
>>
>> Even if we don't trust the backtraces, there's not much room for
>> another activation path. So for all I know, the expectation of the
>> tty logic should have been met. The call was indeed processed from
>> a work queue.
>>
>> Why then does mutex_lock() complain?
> 
> Hmm... capi_recv_message() calls handle_minor_recv() under
> spin_lock_irqsave(), doesn't it?

Well spotted. Indeed it does. That explains it, of course.

The spinlock in question was added by:

commit 053b47ff249b9e0a634dae807f81465205e7c228
Author: Michael Buesch <mb@bu3sch.de>
Date:   Mon Feb 12 00:53:26 2007 -0800

    [PATCH] Workaround CAPI subsystem locking issue
    
    I think the following patch should go into the kernel, until the ISDN/CAPI
    guys create the real fix for this issue.
     
    The issue is a concurrency issue with some internal CAPI data structure
    which can crash the kernel.

    On my FritzCard DSL with the AVM driver it crashes about once a day without
    this workaround patch.  With this workaround patch it's rock-stable (at
    least on UP, but I don't see why this shouldn't work on SMP as well.  But
    maybe I'm missing something.)
    
    This workaround is kind of a sledgehammer which inserts a global lock to
    wrap around all the critical sections.  Of course, this is a scalability
    issue, if you have many ISDN/CAPI cards.  But it prevents a crash.  So I
    vote for this fix to get merged, until people come up with a better
    solution.  Better have a stable kernel that's less scalable, than a
    crashing and useless kernel.
    
So let's cc the author of that patch, and also the good people on the
isdn4linux developer mailing list ...

Any ideas for a fix?

Thanks,
Tilman

-- 
Tilman Schmidt                    E-Mail: tilman@imap.cc
Bonn, Germany
Diese Nachricht besteht zu 100% aus wiederverwerteten Bits.
Ungeöffnet mindestens haltbar bis: (siehe Rückseite)


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* Re: [PATCH 1/2] net/netfilter/ipvs: Move #define KMSG_COMPONENT to Makefile
From: Joe Perches @ 2009-09-30 23:09 UTC (permalink / raw)
  To: Jan Engelhardt
  Cc: Patrick McHardy, David S. Miller, Simon Horman, Julian Anastasov,
	netfilter-devel, coreteam, netdev, linux-kernel, lvs-devel
In-Reply-To: <alpine.LSU.2.00.0910010042540.782@obet.zrqbmnf.qr>

On Thu, 2009-10-01 at 00:46 +0200, Jan Engelhardt wrote:
> On Thursday 2009-10-01 00:37, Joe Perches wrote:
> >This centralizes the definition and removes the
> >replicated #defines from all files
> And increases the length of the command line. Not that Linux does not
> support long command lines (in fact, configure often determines huge
> possible values on the max length test), but sometimes, developers
> have to inspect the command lines anyway for bugs, or something. It
> is already pretty long due to all the compiler flags.

Hi Jan.

I think this increased command line length hardly matters.

I think a reasonable complaint might be that it separates
the definition of a macro from the code.  I think it's
similar to the already used KBUILD_MODNAME macro though.

> How about an #include file for the ipvs private things?

It's not just IPVS, this style could be used treewide
without requiring extra #includes.

cheers, Joe


^ permalink raw reply

* [PATCH] pktgen: Avoid dirtying skb->users when txq is full
From: Eric Dumazet @ 2009-09-30 23:03 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jesper Dangaard Brouer, Robert Olsson, netdev, David S. Miller
In-Reply-To: <20090923174141.1d350103@s6510>

Stephen Hemminger a écrit :
> On Tue, 22 Sep 2009 22:49:02 -0700
> Stephen Hemminger <shemminger@vyatta.com> wrote:
> 
>> I thought others want to know how to get maximum speed of pktgen.
>>
>> 1. Run nothing else (even X11), just a command line
>> 2. Make sure ethernet flow control is disabled
>>    ethtool -A eth0 autoneg off rx off tx off
>> 3. Make sure clocksource is TSC.  On my old SMP Opteron's
>>    needed to get patch since in 2.6.30 or later, the clock guru's
>>    decided to remove it on all non Intel machines.  Look for patch
>>    than enables "tsc=reliable"
>> 4. Compile Ethernet drivers in, the overhead of the indirect
>>    function call required for modules (or cache footprint),
>>    slows things down.
>> 5. Increase transmit ring size to 1000
>>    ethtool -G eth0 tx 1000
>>

Thanks a lot Stephen.

I did some pktgen session tonight and found one contention on skb->users field
that following patch avoids.


Before patch :
------------------------------------------------------------------------------
   PerfTop:    5187 irqs/sec  kernel:100.0% [100000 cycles],  (all, cpu: 0)
------------------------------------------------------------------------------

             samples    pcnt   kernel function
             _______   _____   _______________

            16688.00 - 50.9% : consume_skb
             6541.00 - 20.0% : skb_dma_unmap
             3277.00 - 10.0% : tg3_poll
             1968.00 -  6.0% : mwait_idle
              651.00 -  2.0% : irq_entries_start
              466.00 -  1.4% : _spin_lock
              442.00 -  1.3% : mix_pool_bytes_extract
              373.00 -  1.1% : tg3_msi
              353.00 -  1.1% : read_tsc
              177.00 -  0.5% : sched_clock_local
              176.00 -  0.5% : sched_clock
              137.00 -  0.4% : tick_nohz_stop_sched_tick

After patch:
------------------------------------------------------------------------------
   PerfTop:    3530 irqs/sec  kernel:99.9% [100000 cycles],  (all, cpu: 0)
------------------------------------------------------------------------------

             samples    pcnt   kernel function
             _______   _____   _______________

            17127.00 - 34.0% : tg3_poll
            12691.00 - 25.2% : consume_skb
             5299.00 - 10.5% : skb_dma_unmap
             4179.00 -  8.3% : mwait_idle
             1583.00 -  3.1% : irq_entries_start
             1288.00 -  2.6% : mix_pool_bytes_extract
             1239.00 -  2.5% : tg3_msi
             1062.00 -  2.1% : read_tsc
              583.00 -  1.2% : _spin_lock
              432.00 -  0.9% : sched_clock
              416.00 -  0.8% : sched_clock_local
              360.00 -  0.7% : tick_nohz_stop_sched_tick
              329.00 -  0.7% : ktime_get
              263.00 -  0.5% : _spin_lock_irqsave

I believe we could go further, batching the atomic_inc(&skb->users) we do all the
time, competing with the atomic_dec() done by tx completion handler (possibly run
on other cpu): Reserve XXXXXXX units to the skb->users, and decrement a pktgen
local variable and refill the reserve if necessary, once in a while...


[PATCH] pktgen: Avoid dirtying skb->users when txq is full

We can avoid two atomic ops on skb->users if packet is not going to be
sent to the device (because hardware txqueue is full)

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 4d11c28..6a9ab28 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3439,12 +3439,14 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 	txq = netdev_get_tx_queue(odev, queue_map);
 
 	__netif_tx_lock_bh(txq);
-	atomic_inc(&(pkt_dev->skb->users));
 
-	if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)))
+	if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) {
 		ret = NETDEV_TX_BUSY;
-	else
-		ret = (*xmit)(pkt_dev->skb, odev);
+		pkt_dev->last_ok = 0;
+		goto unlock;
+	}
+	atomic_inc(&(pkt_dev->skb->users));
+	ret = (*xmit)(pkt_dev->skb, odev);
 
 	switch (ret) {
 	case NETDEV_TX_OK:
@@ -3466,6 +3468,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 		atomic_dec(&(pkt_dev->skb->users));
 		pkt_dev->last_ok = 0;
 	}
+unlock:
 	__netif_tx_unlock_bh(txq);
 
 	/* If pkt_dev->count is zero, then run forever */

^ permalink raw reply related

* Re: [PATCH 1/2] net/netfilter/ipvs: Move #define KMSG_COMPONENT to Makefile
From: Jan Engelhardt @ 2009-09-30 22:46 UTC (permalink / raw)
  To: Joe Perches
  Cc: Patrick McHardy, David S. Miller, Simon Horman, Julian Anastasov,
	netfilter-devel, coreteam, netdev, linux-kernel, lvs-devel
In-Reply-To: <0026bcf5aad9ae5036e68fc2dcda9c778d30dc47.1254349375.git.joe@perches.com>


On Thursday 2009-10-01 00:37, Joe Perches wrote:

>This centralizes the definition and removes the
>replicated #defines from all files

And increases the length of the command line. Not that Linux does not
support long command lines (in fact, configure often determines huge
possible values on the max length test), but sometimes, developers
have to inspect the command lines anyway for bugs, or something. It
is already pretty long due to all the compiler flags. Oh what were
the days of DOS programs that allowed to pass in arguments in a
so-called "response file", wish we had that in gcc.

>+ccflags-y += -D "KMSG_COMPONENT=\"IPVS\""
>+ccflags-y += -D "pr_fmt(fmt)=KMSG_COMPONENT \": \" fmt"
>+
> # IPVS transport protocol load balancing support
> ip_vs_proto-objs-y :=
> ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o
>diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
>index 3c7e427..a5283d8 100644
>--- a/net/netfilter/ipvs/ip_vs_app.c
>+++ b/net/netfilter/ipvs/ip_vs_app.c
>@@ -18,9 +18,6 @@
>  *
>  */
> 
>-#define KMSG_COMPONENT "IPVS"
>-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

How about an #include file for the ipvs private things?

^ permalink raw reply

* [PATCH 2/2] net/netfilter: use pr_<level> consistently
From: Joe Perches @ 2009-09-30 22:37 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: David S. Miller, Simon Horman, Julian Anastasov, netfilter-devel,
	coreteam, netdev, linux-kernel, lvs-devel
In-Reply-To: <cover.1254349374.git.joe@perches.com>

Makefile adds a ccflags-y define pr_fmt(fmt)=KBUILD_MODNAME ": " fmt

Many fixed string prefixes are removed
Existing printks and pr_<level>s with KBUILD_MODNAMEs and PFXs are stripped
printks without KERN_ levels are converted to pr_info
Some printks with embedded function names are converted to %s...__func__

Some logging messages now have slightly different content,
but it's standardized content now.

Signed-off-by: Joe Perches <joe@perches.com>
---
 net/netfilter/Makefile                  |    2 +
 net/netfilter/nf_conntrack_acct.c       |   12 ++--
 net/netfilter/nf_conntrack_amanda.c     |    2 +-
 net/netfilter/nf_conntrack_core.c       |   35 ++++-----
 net/netfilter/nf_conntrack_ecache.c     |    5 +-
 net/netfilter/nf_conntrack_expect.c     |    3 +-
 net/netfilter/nf_conntrack_ftp.c        |   31 ++++-----
 net/netfilter/nf_conntrack_h323_main.c  |  114 +++++++++++++++---------------
 net/netfilter/nf_conntrack_irc.c        |   10 +--
 net/netfilter/nf_conntrack_netlink.c    |   12 ++--
 net/netfilter/nf_conntrack_proto_gre.c  |    4 +-
 net/netfilter/nf_conntrack_proto_sctp.c |    9 +--
 net/netfilter/nf_conntrack_proto_tcp.c  |    4 +-
 net/netfilter/nf_conntrack_sane.c       |   17 ++---
 net/netfilter/nf_conntrack_sip.c        |    5 +-
 net/netfilter/nf_conntrack_standalone.c |    2 +-
 net/netfilter/nf_conntrack_tftp.c       |    3 +-
 net/netfilter/nfnetlink.c               |    6 +-
 net/netfilter/nfnetlink_log.c           |   20 +++---
 net/netfilter/nfnetlink_queue.c         |   15 ++--
 net/netfilter/xt_CONNMARK.c             |    2 +-
 net/netfilter/xt_CONNSECMARK.c          |    8 +--
 net/netfilter/xt_DSCP.c                 |    2 +-
 net/netfilter/xt_HL.c                   |    6 +-
 net/netfilter/xt_LED.c                  |   10 +--
 net/netfilter/xt_NFQUEUE.c              |    4 +-
 net/netfilter/xt_SECMARK.c              |   14 ++--
 net/netfilter/xt_TCPMSS.c               |   18 +++---
 net/netfilter/xt_TPROXY.c               |    3 +-
 net/netfilter/xt_cluster.c              |    8 +--
 net/netfilter/xt_connbytes.c            |    2 +-
 net/netfilter/xt_connlimit.c            |    2 +-
 net/netfilter/xt_connmark.c             |    2 +-
 net/netfilter/xt_conntrack.c            |    2 +-
 net/netfilter/xt_dscp.c                 |    2 +-
 net/netfilter/xt_hashlimit.c            |   24 +++----
 net/netfilter/xt_helper.c               |    2 +-
 net/netfilter/xt_hl.c                   |    4 +-
 net/netfilter/xt_limit.c                |    4 +-
 net/netfilter/xt_osf.c                  |    4 +-
 net/netfilter/xt_physdev.c              |    2 +-
 net/netfilter/xt_policy.c               |   11 +--
 net/netfilter/xt_recent.c               |    9 +--
 net/netfilter/xt_state.c                |    2 +-
 net/netfilter/xt_statistic.c            |    2 +-
 net/netfilter/xt_time.c                 |   14 ++--
 46 files changed, 221 insertions(+), 253 deletions(-)

diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 49f62ee..57089b6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,3 +1,5 @@
+ccflags-y += -D "pr_fmt(fmt)=KBUILD_MODNAME \": \" fmt"
+
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
 
 nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 4a1d94a..8ecac97 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -77,7 +77,7 @@ static int nf_conntrack_acct_init_sysctl(struct net *net)
 	net->ct.acct_sysctl_header = register_net_sysctl_table(net,
 			nf_net_netfilter_sysctl_path, table);
 	if (!net->ct.acct_sysctl_header) {
-		printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
+		pr_err("acct: can't register to sysctl.\n");
 		goto out_register;
 	}
 	return 0;
@@ -115,14 +115,16 @@ int nf_conntrack_acct_init(struct net *net)
 
 	if (net_eq(net, &init_net)) {
 #ifdef CONFIG_NF_CT_ACCT
-	printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Please use\n");
-		printk(KERN_WARNING "nf_conntrack.acct=1 kernel parameter, acct=1 nf_conntrack module option or\n");
-		printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
+	pr_warning("CONFIG_NF_CT_ACCT is deprecated and will be removed soon.\n"
+		   "Please use one of the options below to enable it:\n"
+		   "      kernel parameter: nf_conntrack.acct=1\n"
+		   "      module option:    acct=1\n"
+		   "  or  sysctl net.netfilter.nf_conntrack_acct=1\n");
 #endif
 
 		ret = nf_ct_extend_register(&acct_extend);
 		if (ret < 0) {
-			printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
+			pr_err("acct: Unable to register extension\n");
 			goto out_extend_register;
 		}
 	}
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index 07d9d88..81a49f0 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -107,7 +107,7 @@ static int amanda_help(struct sk_buff *skb,
 	dataoff = protoff + sizeof(struct udphdr);
 	if (dataoff >= skb->len) {
 		if (net_ratelimit())
-			printk("amanda_help: skblen = %u\n", skb->len);
+			pr_info("amanda_help: skblen = %u\n", skb->len);
 		return NF_ACCEPT;
 	}
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 7c9ec3d..2eef0ae 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -554,9 +554,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
 		if (!early_drop(net, hash)) {
 			atomic_dec(&net->ct.count);
 			if (net_ratelimit())
-				printk(KERN_WARNING
-				       "nf_conntrack: table full, dropping"
-				       " packet.\n");
+				pr_warning("table full, dropping packet.\n");
 			return ERR_PTR(-ENOMEM);
 		}
 	}
@@ -567,7 +565,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
 	 */
 	ct = kmem_cache_alloc(nf_conntrack_cachep, gfp);
 	if (ct == NULL) {
-		pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
+		pr_debug("%s(): Can't alloc conntrack.\n", __func__);
 		atomic_dec(&net->ct.count);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -636,7 +634,7 @@ init_conntrack(struct net *net,
 
 	if (!l4proto->new(ct, skb, dataoff)) {
 		nf_conntrack_free(ct);
-		pr_debug("init conntrack: can't track with proto module\n");
+		pr_debug("Can't track with proto module\n");
 		return NULL;
 	}
 
@@ -646,7 +644,7 @@ init_conntrack(struct net *net,
 	spin_lock_bh(&nf_conntrack_lock);
 	exp = nf_ct_find_expectation(net, tuple);
 	if (exp) {
-		pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
+		pr_debug("expectation arrives ct=%p exp=%p\n",
 			 ct, exp);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
 		__set_bit(IPS_EXPECTED_BIT, &ct->status);
@@ -704,7 +702,7 @@ resolve_normal_ct(struct net *net,
 	if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
 			     dataoff, l3num, protonum, &tuple, l3proto,
 			     l4proto)) {
-		pr_debug("resolve_normal_ct: Can't get tuple\n");
+		pr_debug("%s(): Can't get tuple\n", __func__);
 		return NULL;
 	}
 
@@ -727,14 +725,13 @@ resolve_normal_ct(struct net *net,
 	} else {
 		/* Once we've had two way comms, always ESTABLISHED. */
 		if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
-			pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
+			pr_debug("in: normal packet for %p\n", ct);
 			*ctinfo = IP_CT_ESTABLISHED;
 		} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
-			pr_debug("nf_conntrack_in: related packet for %p\n",
-				 ct);
+			pr_debug("in: related packet for %p\n", ct);
 			*ctinfo = IP_CT_RELATED;
 		} else {
-			pr_debug("nf_conntrack_in: new packet for %p\n", ct);
+			pr_debug("in: new packet for %p\n", ct);
 			*ctinfo = IP_CT_NEW;
 		}
 		*set_reply = 0;
@@ -768,7 +765,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
 	ret = l3proto->get_l4proto(skb, skb_network_offset(skb),
 				   &dataoff, &protonum);
 	if (ret <= 0) {
-		pr_debug("not prepared to track yet or error occured\n");
+		pr_debug("not prepared to track yet or error occurred\n");
 		NF_CT_STAT_INC_ATOMIC(net, error);
 		NF_CT_STAT_INC_ATOMIC(net, invalid);
 		return -ret;
@@ -808,7 +805,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
 	if (ret <= 0) {
 		/* Invalid: inverse of the return code tells
 		 * the netfilter core what to do */
-		pr_debug("nf_conntrack_in: Can't track with proto module\n");
+		pr_debug("in: Can't track with proto module\n");
 		nf_conntrack_put(skb->nfct);
 		skb->nfct = NULL;
 		NF_CT_STAT_INC_ATOMIC(net, invalid);
@@ -1167,7 +1164,7 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls)
 					get_order(sz));
 	if (!hash) {
 		*vmalloced = 1;
-		printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
+		pr_warning("falling back to vmalloc.\n");
 		hash = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
 	}
 
@@ -1260,15 +1257,15 @@ static int nf_conntrack_init_init_net(void)
 	}
 	nf_conntrack_max = max_factor * nf_conntrack_htable_size;
 
-	printk("nf_conntrack version %s (%u buckets, %d max)\n",
-	       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
-	       nf_conntrack_max);
+	pr_info("version %s (%u buckets, %d max)\n",
+		NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
+		nf_conntrack_max);
 
 	nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
 						sizeof(struct nf_conn),
 						0, SLAB_DESTROY_BY_RCU, NULL);
 	if (!nf_conntrack_cachep) {
-		printk(KERN_ERR "Unable to create nf_conn slab cache\n");
+		pr_err("Unable to create slab cache\n");
 		ret = -ENOMEM;
 		goto err_cache;
 	}
@@ -1313,7 +1310,7 @@ static int nf_conntrack_init_net(struct net *net)
 					     &net->ct.hash_vmalloc, 1);
 	if (!net->ct.hash) {
 		ret = -ENOMEM;
-		printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
+		pr_err("Unable to create hash table\n");
 		goto err_hash;
 	}
 	ret = nf_conntrack_expect_init(net);
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index aee560b..a4b3a13 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -193,7 +193,7 @@ static int nf_conntrack_event_init_sysctl(struct net *net)
 		register_net_sysctl_table(net,
 					  nf_net_netfilter_sysctl_path, table);
 	if (!net->ct.event_sysctl_header) {
-		printk(KERN_ERR "nf_ct_event: can't register to sysctl.\n");
+		pr_err("event: can't register to sysctl.\n");
 		goto out_register;
 	}
 	return 0;
@@ -233,8 +233,7 @@ int nf_conntrack_ecache_init(struct net *net)
 	if (net_eq(net, &init_net)) {
 		ret = nf_ct_extend_register(&event_extend);
 		if (ret < 0) {
-			printk(KERN_ERR "nf_ct_event: Unable to register "
-					"event extension.\n");
+			pr_err("event: Unable to register event extension.\n");
 			goto out_extend_register;
 		}
 	}
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 2032dfe..1b3c02b 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -404,8 +404,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
 
 	if (net->ct.expect_count >= nf_ct_expect_max) {
 		if (net_ratelimit())
-			printk(KERN_WARNING
-			       "nf_conntrack: expectation table full\n");
+			pr_warning("expectation table full\n");
 		ret = -EMFILE;
 	}
 out:
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 5509dd1..64d3c6f 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -201,7 +201,7 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
 	}
 	delim = data[0];
 	if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) {
-		pr_debug("try_eprt: invalid delimitter.\n");
+		pr_debug("try_eprt: invalid delimiter.\n");
 		return 0;
 	}
 
@@ -277,9 +277,9 @@ static int find_pattern(const char *data, size_t dlen,
 #if 0
 		size_t i;
 
-		pr_debug("ftp: string mismatch\n");
+		pr_debug("string mismatch\n");
 		for (i = 0; i < plen; i++) {
-			pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
+			pr_debug("char %u `%c'(%u) vs `%c'(%u)\n",
 				 i, data[i], data[i],
 				 pattern[i], pattern[i]);
 		}
@@ -368,7 +368,7 @@ static int help(struct sk_buff *skb,
 	/* Until there's been traffic both ways, don't look in packets. */
 	if (ctinfo != IP_CT_ESTABLISHED
 	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
-		pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
+		pr_debug("Conntrackinfo = %u\n", ctinfo);
 		return NF_ACCEPT;
 	}
 
@@ -379,7 +379,7 @@ static int help(struct sk_buff *skb,
 	dataoff = protoff + th->doff * 4;
 	/* No data? */
 	if (dataoff >= skb->len) {
-		pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
+		pr_debug("dataoff(%u) >= skblen(%u)\n", dataoff,
 			 skb->len);
 		return NF_ACCEPT;
 	}
@@ -395,7 +395,7 @@ static int help(struct sk_buff *skb,
 	/* Look up to see if we're just after a \n. */
 	if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
 		/* Now if this ends in \n, update ftp info. */
-		pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
+		pr_debug("wrong seq pos %s(%u) or %s(%u)\n",
 			 ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
 			 ct_ftp_info->seq_aft_nl[dir][0],
 			 ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
@@ -426,7 +426,7 @@ static int help(struct sk_buff *skb,
 		   connection tracking, not packet filtering.
 		   However, it is necessary for accurate tracking in
 		   this case. */
-		pr_debug("conntrack_ftp: partial %s %u+%u\n",
+		pr_debug("partial %s %u+%u\n",
 			 search[dir][i].pattern,  ntohl(th->seq), datalen);
 		ret = NF_DROP;
 		goto out;
@@ -435,7 +435,7 @@ static int help(struct sk_buff *skb,
 		goto out_update_nl;
 	}
 
-	pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
+	pr_debug("match `%.*s' (%u bytes at %u)\n",
 		 matchlen, fb_ptr + matchoff,
 		 matchlen, ntohl(th->seq) + matchoff);
 
@@ -459,11 +459,11 @@ static int help(struct sk_buff *skb,
 		   different IP address.  Simply don't record it for
 		   NAT. */
 		if (cmd.l3num == PF_INET) {
-			pr_debug("conntrack_ftp: NOT RECORDING: %pI4 != %pI4\n",
+			pr_debug("NOT RECORDING: %pI4 != %pI4\n",
 				 &cmd.u3.ip,
 				 &ct->tuplehash[dir].tuple.src.u3.ip);
 		} else {
-			pr_debug("conntrack_ftp: NOT RECORDING: %pI6 != %pI6\n",
+			pr_debug("NOT RECORDING: %pI6 != %pI6\n",
 				 cmd.u3.ip6,
 				 ct->tuplehash[dir].tuple.src.u3.ip6);
 		}
@@ -527,8 +527,7 @@ static void nf_conntrack_ftp_fini(void)
 			if (ftp[i][j].me == NULL)
 				continue;
 
-			pr_debug("nf_ct_ftp: unregistering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("unregistering helper for pf: %d port: %d\n",
 				 ftp[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&ftp[i][j]);
 		}
@@ -567,14 +566,12 @@ static int __init nf_conntrack_ftp_init(void)
 				sprintf(tmpname, "ftp-%d", ports[i]);
 			ftp[i][j].name = tmpname;
 
-			pr_debug("nf_ct_ftp: registering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("registering helper for pf: %d port: %d\n",
 				 ftp[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&ftp[i][j]);
 			if (ret) {
-				printk("nf_ct_ftp: failed to register helper "
-				       " for pf: %d port: %d\n",
-					ftp[i][j].tuple.src.l3num, ports[i]);
+				pr_err("failed to register helper for pf: %d port: %d\n",
+				       ftp[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_ftp_fini();
 				return ret;
 			}
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 6636949..e7895d0 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -145,7 +145,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
 		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
 			/* Netmeeting sends TPKT header and data separately */
 			if (info->tpkt_len[dir] > 0) {
-				pr_debug("nf_ct_h323: previous packet "
+				pr_debug("h323: previous packet "
 					 "indicated separate TPKT data of %hu "
 					 "bytes\n", info->tpkt_len[dir]);
 				if (info->tpkt_len[dir] <= tcpdatalen) {
@@ -158,7 +158,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
 				}
 
 				/* Fragmented TPKT */
-				pr_debug("nf_ct_h323: fragmented TPKT\n");
+				pr_debug("h323: fragmented TPKT\n");
 				goto clear_out;
 			}
 
@@ -185,7 +185,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
 	if (tpktlen > tcpdatalen) {
 		if (tcpdatalen == 4) {	/* Separate TPKT header */
 			/* Netmeeting sends TPKT header and data separately */
-			pr_debug("nf_ct_h323: separate TPKT header indicates "
+			pr_debug("h323: separate TPKT header indicates "
 				 "there will be TPKT data of %hu bytes\n",
 				 tpktlen - 4);
 			info->tpkt_len[dir] = tpktlen - 4;
@@ -193,7 +193,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
 		}
 
 		if (net_ratelimit())
-			printk("nf_ct_h323: incomplete TPKT (fragmented?)\n");
+			pr_info("h323: incomplete TPKT (fragmented?)\n");
 		goto clear_out;
 	}
 
@@ -302,9 +302,9 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
 	} else {		/* Conntrack only */
 		if (nf_ct_expect_related(rtp_exp) == 0) {
 			if (nf_ct_expect_related(rtcp_exp) == 0) {
-				pr_debug("nf_ct_h323: expect RTP ");
+				pr_debug("h323: expect RTP ");
 				nf_ct_dump_tuple(&rtp_exp->tuple);
-				pr_debug("nf_ct_h323: expect RTCP ");
+				pr_debug("h323: expect RTCP ");
 				nf_ct_dump_tuple(&rtcp_exp->tuple);
 			} else {
 				nf_ct_unexpect_related(rtp_exp);
@@ -359,7 +359,7 @@ static int expect_t120(struct sk_buff *skb,
 			       port, exp);
 	} else {		/* Conntrack only */
 		if (nf_ct_expect_related(exp) == 0) {
-			pr_debug("nf_ct_h323: expect T.120 ");
+			pr_debug("h323: expect T.120 ");
 			nf_ct_dump_tuple(&exp->tuple);
 		} else
 			ret = -1;
@@ -407,7 +407,7 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
 {
 	int ret;
 
-	pr_debug("nf_ct_h323: OpenLogicalChannel\n");
+	pr_debug("h323: OpenLogicalChannel\n");
 
 	if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
 	    eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
@@ -467,7 +467,7 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
 	H2250LogicalChannelAckParameters *ack;
 	int ret;
 
-	pr_debug("nf_ct_h323: OpenLogicalChannelAck\n");
+	pr_debug("h323: OpenLogicalChannelAck\n");
 
 	if ((olca->options &
 	     eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
@@ -538,7 +538,7 @@ static int process_h245(struct sk_buff *skb, struct nf_conn *ct,
 			return process_olc(skb, ct, ctinfo, data, dataoff,
 					   &mscm->request.openLogicalChannel);
 		}
-		pr_debug("nf_ct_h323: H.245 Request %d\n",
+		pr_debug("h323: H.245 Request %d\n",
 			 mscm->request.choice);
 		break;
 	case eMultimediaSystemControlMessage_response:
@@ -548,11 +548,11 @@ static int process_h245(struct sk_buff *skb, struct nf_conn *ct,
 					    &mscm->response.
 					    openLogicalChannelAck);
 		}
-		pr_debug("nf_ct_h323: H.245 Response %d\n",
+		pr_debug("h323: H.245 Response %d\n",
 			 mscm->response.choice);
 		break;
 	default:
-		pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice);
+		pr_debug("h323: H.245 signal %d\n", mscm->choice);
 		break;
 	}
 
@@ -574,21 +574,21 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
 	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
 		return NF_ACCEPT;
 	}
-	pr_debug("nf_ct_h245: skblen = %u\n", skb->len);
+	pr_debug("h245: skblen = %u\n", skb->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
 	/* Process each TPKT */
 	while (get_tpkt_data(skb, protoff, ct, ctinfo,
 			     &data, &datalen, &dataoff)) {
-		pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
+		pr_debug("h245: TPKT len=%d ", datalen);
 		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 		/* Decode H.245 signal */
 		ret = DecodeMultimediaSystemControlMessage(data, datalen,
 							   &mscm);
 		if (ret < 0) {
-			pr_debug("nf_ct_h245: decoding error: %s\n",
+			pr_debug("h245: decoding error: %s\n",
 				 ret == H323_ERROR_BOUND ?
 				 "out of bound" : "out of range");
 			/* We don't drop when decoding error */
@@ -606,7 +606,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
       drop:
 	spin_unlock_bh(&nf_h323_lock);
 	if (net_ratelimit())
-		printk("nf_ct_h245: packet dropped\n");
+		pr_info("h245: packet dropped\n");
 	return NF_DROP;
 }
 
@@ -695,7 +695,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
 			       port, exp);
 	} else {		/* Conntrack only */
 		if (nf_ct_expect_related(exp) == 0) {
-			pr_debug("nf_ct_q931: expect H.245 ");
+			pr_debug("q931: expect H.245 ");
 			nf_ct_dump_tuple(&exp->tuple);
 		} else
 			ret = -1;
@@ -789,7 +789,7 @@ static int expect_callforwarding(struct sk_buff *skb,
 	if (callforward_filter &&
 	    callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
 				  nf_ct_l3num(ct))) {
-		pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
+		pr_debug("q931: Call Forwarding not tracked\n");
 		return 0;
 	}
 
@@ -811,7 +811,7 @@ static int expect_callforwarding(struct sk_buff *skb,
 					 taddr, port, exp);
 	} else {		/* Conntrack only */
 		if (nf_ct_expect_related(exp) == 0) {
-			pr_debug("nf_ct_q931: expect Call Forwarding ");
+			pr_debug("q931: expect Call Forwarding ");
 			nf_ct_dump_tuple(&exp->tuple);
 		} else
 			ret = -1;
@@ -835,7 +835,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
 	union nf_inet_addr addr;
 	typeof(set_h225_addr_hook) set_h225_addr;
 
-	pr_debug("nf_ct_q931: Setup\n");
+	pr_debug("q931: Setup\n");
 
 	if (setup->options & eSetup_UUIE_h245Address) {
 		ret = expect_h245(skb, ct, ctinfo, data, dataoff,
@@ -850,7 +850,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
 	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
-		pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu\n",
+		pr_debug("q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu\n",
 			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3,
 			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
 		ret = set_h225_addr(skb, data, dataoff,
@@ -866,7 +866,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
 	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
-		pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu\n",
+		pr_debug("q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu\n",
 			 &addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3,
 			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
 		ret = set_h225_addr(skb, data, dataoff,
@@ -899,7 +899,7 @@ static int process_callproceeding(struct sk_buff *skb,
 	int ret;
 	int i;
 
-	pr_debug("nf_ct_q931: CallProceeding\n");
+	pr_debug("q931: CallProceeding\n");
 
 	if (callproc->options & eCallProceeding_UUIE_h245Address) {
 		ret = expect_h245(skb, ct, ctinfo, data, dataoff,
@@ -929,7 +929,7 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
 	int ret;
 	int i;
 
-	pr_debug("nf_ct_q931: Connect\n");
+	pr_debug("q931: Connect\n");
 
 	if (connect->options & eConnect_UUIE_h245Address) {
 		ret = expect_h245(skb, ct, ctinfo, data, dataoff,
@@ -959,7 +959,7 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
 	int ret;
 	int i;
 
-	pr_debug("nf_ct_q931: Alerting\n");
+	pr_debug("q931: Alerting\n");
 
 	if (alert->options & eAlerting_UUIE_h245Address) {
 		ret = expect_h245(skb, ct, ctinfo, data, dataoff,
@@ -989,7 +989,7 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
 	int ret;
 	int i;
 
-	pr_debug("nf_ct_q931: Facility\n");
+	pr_debug("q931: Facility\n");
 
 	if (facility->reason.choice == eFacilityReason_callForwarded) {
 		if (facility->options & eFacility_UUIE_alternativeAddress)
@@ -1028,7 +1028,7 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
 	int ret;
 	int i;
 
-	pr_debug("nf_ct_q931: Progress\n");
+	pr_debug("q931: Progress\n");
 
 	if (progress->options & eProgress_UUIE_h245Address) {
 		ret = expect_h245(skb, ct, ctinfo, data, dataoff,
@@ -1085,7 +1085,7 @@ static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
 				       &pdu->h323_message_body.progress);
 		break;
 	default:
-		pr_debug("nf_ct_q931: Q.931 signal %d\n",
+		pr_debug("q931: Q.931 signal %d\n",
 			 pdu->h323_message_body.choice);
 		break;
 	}
@@ -1120,20 +1120,20 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
 	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
 		return NF_ACCEPT;
 	}
-	pr_debug("nf_ct_q931: skblen = %u\n", skb->len);
+	pr_debug("q931: skblen = %u\n", skb->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
 	/* Process each TPKT */
 	while (get_tpkt_data(skb, protoff, ct, ctinfo,
 			     &data, &datalen, &dataoff)) {
-		pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
+		pr_debug("q931: TPKT len=%d ", datalen);
 		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 		/* Decode Q.931 signal */
 		ret = DecodeQ931(data, datalen, &q931);
 		if (ret < 0) {
-			pr_debug("nf_ct_q931: decoding error: %s\n",
+			pr_debug("q931: decoding error: %s\n",
 				 ret == H323_ERROR_BOUND ?
 				 "out of bound" : "out of range");
 			/* We don't drop when decoding error */
@@ -1151,7 +1151,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
       drop:
 	spin_unlock_bh(&nf_h323_lock);
 	if (net_ratelimit())
-		printk("nf_ct_q931: packet dropped\n");
+		pr_info("q931: packet dropped\n");
 	return NF_DROP;
 }
 
@@ -1277,7 +1277,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
 		ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
 	} else {		/* Conntrack only */
 		if (nf_ct_expect_related(exp) == 0) {
-			pr_debug("nf_ct_ras: expect Q.931 ");
+			pr_debug("ras: expect Q.931 ");
 			nf_ct_dump_tuple(&exp->tuple);
 
 			/* Save port for looking up expect in processing RCF */
@@ -1298,7 +1298,7 @@ static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
 {
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	pr_debug("nf_ct_ras: GRQ\n");
+	pr_debug("ras: GRQ\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK)	/* NATed */
@@ -1318,7 +1318,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
 	union nf_inet_addr addr;
 	struct nf_conntrack_expect *exp;
 
-	pr_debug("nf_ct_ras: GCF\n");
+	pr_debug("ras: GCF\n");
 
 	if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
 		return 0;
@@ -1341,7 +1341,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
 	exp->helper = nf_conntrack_helper_ras;
 
 	if (nf_ct_expect_related(exp) == 0) {
-		pr_debug("nf_ct_ras: expect RAS ");
+		pr_debug("ras: expect RAS ");
 		nf_ct_dump_tuple(&exp->tuple);
 	} else
 		ret = -1;
@@ -1360,7 +1360,7 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
 	int ret;
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	pr_debug("nf_ct_ras: RRQ\n");
+	pr_debug("ras: RRQ\n");
 
 	ret = expect_q931(skb, ct, ctinfo, data,
 			  rrq->callSignalAddress.item,
@@ -1378,7 +1378,7 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
 	}
 
 	if (rrq->options & eRegistrationRequest_timeToLive) {
-		pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
+		pr_debug("ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
 		info->timeout = rrq->timeToLive;
 	} else
 		info->timeout = default_rrq_ttl;
@@ -1397,7 +1397,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
 	struct nf_conntrack_expect *exp;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	pr_debug("nf_ct_ras: RCF\n");
+	pr_debug("ras: RCF\n");
 
 	set_sig_addr = rcu_dereference(set_sig_addr_hook);
 	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1409,12 +1409,12 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
 	}
 
 	if (rcf->options & eRegistrationConfirm_timeToLive) {
-		pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
+		pr_debug("ras: RCF TTL = %u seconds\n", rcf->timeToLive);
 		info->timeout = rcf->timeToLive;
 	}
 
 	if (info->timeout > 0) {
-		pr_debug("nf_ct_ras: set RAS connection timeout to "
+		pr_debug("ras: set RAS connection timeout to "
 			 "%u seconds\n", info->timeout);
 		nf_ct_refresh(ct, skb, info->timeout * HZ);
 
@@ -1423,7 +1423,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
 		exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
 				  info->sig_port[!dir]);
 		if (exp) {
-			pr_debug("nf_ct_ras: set Q.931 expect "
+			pr_debug("ras: set Q.931 expect "
 				 "timeout to %u seconds for",
 				 info->timeout);
 			nf_ct_dump_tuple(&exp->tuple);
@@ -1445,7 +1445,7 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
 	int ret;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	pr_debug("nf_ct_ras: URQ\n");
+	pr_debug("ras: URQ\n");
 
 	set_sig_addr = rcu_dereference(set_sig_addr_hook);
 	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1478,7 +1478,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
 	union nf_inet_addr addr;
 	typeof(set_h225_addr_hook) set_h225_addr;
 
-	pr_debug("nf_ct_ras: ARQ\n");
+	pr_debug("ras: ARQ\n");
 
 	set_h225_addr = rcu_dereference(set_h225_addr_hook);
 	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
@@ -1521,7 +1521,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
 	struct nf_conntrack_expect *exp;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	pr_debug("nf_ct_ras: ACF\n");
+	pr_debug("ras: ACF\n");
 
 	if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
 			   &addr, &port))
@@ -1546,7 +1546,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
 	exp->helper = nf_conntrack_helper_q931;
 
 	if (nf_ct_expect_related(exp) == 0) {
-		pr_debug("nf_ct_ras: expect Q.931 ");
+		pr_debug("ras: expect Q.931 ");
 		nf_ct_dump_tuple(&exp->tuple);
 	} else
 		ret = -1;
@@ -1563,7 +1563,7 @@ static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
 {
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	pr_debug("nf_ct_ras: LRQ\n");
+	pr_debug("ras: LRQ\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK)
@@ -1583,7 +1583,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
 	union nf_inet_addr addr;
 	struct nf_conntrack_expect *exp;
 
-	pr_debug("nf_ct_ras: LCF\n");
+	pr_debug("ras: LCF\n");
 
 	if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
 			   &addr, &port))
@@ -1599,7 +1599,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
 	exp->helper = nf_conntrack_helper_q931;
 
 	if (nf_ct_expect_related(exp) == 0) {
-		pr_debug("nf_ct_ras: expect Q.931 ");
+		pr_debug("ras: expect Q.931 ");
 		nf_ct_dump_tuple(&exp->tuple);
 	} else
 		ret = -1;
@@ -1620,7 +1620,7 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
 	typeof(set_ras_addr_hook) set_ras_addr;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	pr_debug("nf_ct_ras: IRR\n");
+	pr_debug("ras: IRR\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
@@ -1679,7 +1679,7 @@ static int process_ras(struct sk_buff *skb, struct nf_conn *ct,
 		return process_irr(skb, ct, ctinfo, data,
 				   &ras->infoRequestResponse);
 	default:
-		pr_debug("nf_ct_ras: RAS message %d\n", ras->choice);
+		pr_debug("ras: RAS message %d\n", ras->choice);
 		break;
 	}
 
@@ -1695,7 +1695,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
 	int datalen = 0;
 	int ret;
 
-	pr_debug("nf_ct_ras: skblen = %u\n", skb->len);
+	pr_debug("ras: skblen = %u\n", skb->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
@@ -1703,13 +1703,13 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
 	data = get_udp_data(skb, protoff, &datalen);
 	if (data == NULL)
 		goto accept;
-	pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
+	pr_debug("ras: RAS message len=%d ", datalen);
 	nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 	/* Decode RAS message */
 	ret = DecodeRasMessage(data, datalen, &ras);
 	if (ret < 0) {
-		pr_debug("nf_ct_ras: decoding error: %s\n",
+		pr_debug("ras: decoding error: %s\n",
 			 ret == H323_ERROR_BOUND ?
 			 "out of bound" : "out of range");
 		goto accept;
@@ -1726,7 +1726,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
       drop:
 	spin_unlock_bh(&nf_h323_lock);
 	if (net_ratelimit())
-		printk("nf_ct_ras: packet dropped\n");
+		pr_info("ras: packet dropped\n");
 	return NF_DROP;
 }
 
@@ -1766,7 +1766,7 @@ static void __exit nf_conntrack_h323_fini(void)
 	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
 	nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
 	kfree(h323_buffer);
-	pr_debug("nf_ct_h323: fini\n");
+	pr_debug("h323: fini\n");
 }
 
 /****************************************************************************/
@@ -1792,7 +1792,7 @@ static int __init nf_conntrack_h323_init(void)
 	ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
 	if (ret < 0)
 		goto err5;
-	pr_debug("nf_ct_h323: init success\n");
+	pr_debug("h323: init success\n");
 	return 0;
 
 err5:
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 8bd98c8..f9ac790 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -186,8 +186,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 			if (tuple->src.u3.ip != dcc_ip &&
 			    tuple->dst.u3.ip != dcc_ip) {
 				if (net_ratelimit())
-					printk(KERN_WARNING
-						"Forged DCC command from %pI4: %pI4:%u\n",
+					pr_warning("Forged DCC command from %pI4: %pI4:%u\n",
 						&tuple->src.u3.ip,
 						&dcc_ip, dcc_port);
 				continue;
@@ -234,7 +233,7 @@ static int __init nf_conntrack_irc_init(void)
 	char *tmpname;
 
 	if (max_dcc_channels < 1) {
-		printk("nf_ct_irc: max_dcc_channels must not be zero\n");
+		pr_info("max_dcc_channels must not be zero\n");
 		return -EINVAL;
 	}
 
@@ -266,9 +265,8 @@ static int __init nf_conntrack_irc_init(void)
 
 		ret = nf_conntrack_helper_register(&irc[i]);
 		if (ret) {
-			printk("nf_ct_irc: failed to register helper "
-			       "for pf: %u port: %u\n",
-			       irc[i].tuple.src.l3num, ports[i]);
+			pr_info("failed to register helper for pf: %u port: %u\n",
+				irc[i].tuple.src.l3num, ports[i]);
 			nf_conntrack_irc_fini();
 			return ret;
 		}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 59d8064..334f9eb 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1942,29 +1942,29 @@ static int __init ctnetlink_init(void)
 {
 	int ret;
 
-	printk("ctnetlink v%s: registering with nfnetlink.\n", version);
+	pr_info("version %s: registering with nfnetlink.\n", version);
 	ret = nfnetlink_subsys_register(&ctnl_subsys);
 	if (ret < 0) {
-		printk("ctnetlink_init: cannot register with nfnetlink.\n");
+		pr_err("%s(): cannot register with nfnetlink.\n", __func__);
 		goto err_out;
 	}
 
 	ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
 	if (ret < 0) {
-		printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
+		pr_err("%s(): cannot register exp with nfnetlink.\n", __func__);
 		goto err_unreg_subsys;
 	}
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 	ret = nf_conntrack_register_notifier(&ctnl_notifier);
 	if (ret < 0) {
-		printk("ctnetlink_init: cannot register notifier.\n");
+		pr_err("%s(): cannot register notifier.\n", __func__);
 		goto err_unreg_exp_subsys;
 	}
 
 	ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp);
 	if (ret < 0) {
-		printk("ctnetlink_init: cannot expect register notifier.\n");
+		pr_err("%s(): cannot expect register notifier.\n", __func__);
 		goto err_unreg_notifier;
 	}
 #endif
@@ -1985,7 +1985,7 @@ err_out:
 
 static void __exit ctnetlink_exit(void)
 {
-	printk("ctnetlink: unregistering from nfnetlink.\n");
+	pr_info("%s(): unregistering from nfnetlink.\n", __func__);
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 	nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index a54a0af..7314c89 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -253,7 +253,7 @@ static int gre_packet(struct nf_conn *ct,
 static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
 		    unsigned int dataoff)
 {
-	pr_debug(": ");
+	pr_debug("new: ");
 	nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 
 	/* initialize to sane value.  Ideally a conntrack helper
@@ -269,7 +269,7 @@ static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
 static void gre_destroy(struct nf_conn *ct)
 {
 	struct nf_conn *master = ct->master;
-	pr_debug(" entering\n");
+	pr_debug("entering\n");
 
 	if (!master)
 		pr_debug("no master !?!\n");
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index c10e6f3..2b6cc42 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -344,8 +344,7 @@ static int sctp_packet(struct nf_conn *ct,
 
 		/* Invalid */
 		if (new_state == SCTP_CONNTRACK_MAX) {
-			pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
-				 "conntrack=%u\n",
+			pr_debug("Invalid dir=%i ctype=%u conntrack=%u\n",
 				 dir, sch->type, old_state);
 			goto out_unlock;
 		}
@@ -422,7 +421,7 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
 		/* Invalid: delete conntrack */
 		if (new_state == SCTP_CONNTRACK_NONE ||
 		    new_state == SCTP_CONNTRACK_MAX) {
-			pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
+			pr_debug("invalid new deleting.\n");
 			return false;
 		}
 
@@ -721,12 +720,12 @@ static int __init nf_conntrack_proto_sctp_init(void)
 
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
 	if (ret) {
-		printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
+		pr_info("nf_conntrack_l4proto_sctp4: protocol register failed\n");
 		goto out;
 	}
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
 	if (ret) {
-		printk("nf_conntrack_l4proto_sctp6: protocol register failed\n");
+		pr_info("nf_conntrack_l4proto_sctp6: protocol register failed\n");
 		goto cleanup_sctp4;
 	}
 
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 97a82ba..9eb5e85 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -932,7 +932,7 @@ static int tcp_packet(struct nf_conn *ct,
 		return NF_ACCEPT;
 	case TCP_CONNTRACK_MAX:
 		/* Invalid packet */
-		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
+		pr_debug("tcp: Invalid dir=%i index=%u ostate=%u\n",
 			 dir, get_conntrack_index(th), old_state);
 		spin_unlock_bh(&ct->lock);
 		if (LOG_INVALID(net, IPPROTO_TCP))
@@ -1053,7 +1053,7 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 
 	/* Invalid: delete conntrack */
 	if (new_state >= TCP_CONNTRACK_MAX) {
-		pr_debug("nf_ct_tcp: invalid new deleting.\n");
+		pr_debug("tcp: invalid new deleting.\n");
 		return false;
 	}
 
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index dcfecbb..28d90d5 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -120,14 +120,14 @@ static int help(struct sk_buff *skb,
 	ct_sane_info->state = SANE_STATE_NORMAL;
 
 	if (datalen < sizeof(struct sane_reply_net_start)) {
-		pr_debug("nf_ct_sane: NET_START reply too short\n");
+		pr_debug("NET_START reply too short\n");
 		goto out;
 	}
 
 	reply = sb_ptr;
 	if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
 		/* saned refused the command */
-		pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
+		pr_debug("unsuccessful SANE_STATUS = %u\n",
 			 ntohl(reply->status));
 		goto out;
 	}
@@ -147,7 +147,7 @@ static int help(struct sk_buff *skb,
 			  &tuple->src.u3, &tuple->dst.u3,
 			  IPPROTO_TCP, NULL, &reply->port);
 
-	pr_debug("nf_ct_sane: expect: ");
+	pr_debug("expect: ");
 	nf_ct_dump_tuple(&exp->tuple);
 
 	/* Can't expect this?  Best to drop packet now. */
@@ -176,8 +176,7 @@ static void nf_conntrack_sane_fini(void)
 
 	for (i = 0; i < ports_c; i++) {
 		for (j = 0; j < 2; j++) {
-			pr_debug("nf_ct_sane: unregistering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("unregistering helper for pf: %d port: %d\n",
 				 sane[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&sane[i][j]);
 		}
@@ -216,14 +215,12 @@ static int __init nf_conntrack_sane_init(void)
 				sprintf(tmpname, "sane-%d", ports[i]);
 			sane[i][j].name = tmpname;
 
-			pr_debug("nf_ct_sane: registering helper for pf: %d "
-				 "port: %d\n",
+			pr_debug("registering helper for pf: %d port: %d\n",
 				 sane[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&sane[i][j]);
 			if (ret) {
-				printk(KERN_ERR "nf_ct_sane: failed to "
-				       "register helper for pf: %d port: %d\n",
-					sane[i][j].tuple.src.l3num, ports[i]);
+				pr_err("failed to register helper for pf: %d port: %d\n",
+				       sane[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_sane_fini();
 				return ret;
 			}
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 4b57216..0cd79c7 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1363,9 +1363,8 @@ static int __init nf_conntrack_sip_init(void)
 
 			ret = nf_conntrack_helper_register(&sip[i][j]);
 			if (ret) {
-				printk("nf_ct_sip: failed to register helper "
-				       "for pf: %u port: %u\n",
-				       sip[i][j].tuple.src.l3num, ports[i]);
+				pr_info("failed to register helper for pf: %u port: %u\n",
+					sip[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_sip_fini();
 				return ret;
 			}
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 1935153..2dad630 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -445,7 +445,7 @@ out_kmemdup:
 	if (net_eq(net, &init_net))
 		unregister_sysctl_table(nf_ct_netfilter_header);
 out:
-	printk("nf_conntrack: can't register to sysctl.\n");
+	pr_info("can't register to sysctl.\n");
 	return -ENOMEM;
 }
 
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index 46e646b..0dcd4de 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -138,8 +138,7 @@ static int __init nf_conntrack_tftp_init(void)
 
 			ret = nf_conntrack_helper_register(&tftp[i][j]);
 			if (ret) {
-				printk("nf_ct_tftp: failed to register helper "
-				       "for pf: %u port: %u\n",
+				pr_info("failed to register helper for pf: %u port: %u\n",
 					tftp[i][j].tuple.src.l3num, ports[i]);
 				nf_conntrack_tftp_fini();
 				return ret;
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index eedc0c1..51d2920 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -186,19 +186,19 @@ static void nfnetlink_rcv(struct sk_buff *skb)
 
 static void __exit nfnetlink_exit(void)
 {
-	printk("Removing netfilter NETLINK layer.\n");
+	pr_info("Removing netfilter NETLINK layer.\n");
 	netlink_kernel_release(nfnl);
 	return;
 }
 
 static int __init nfnetlink_init(void)
 {
-	printk("Netfilter messages via NETLINK v%s.\n", nfversion);
+	pr_info("Netfilter messages via NETLINK v%s.\n", nfversion);
 
 	nfnl = netlink_kernel_create(&init_net, NETLINK_NETFILTER, NFNLGRP_MAX,
 				     nfnetlink_rcv, NULL, THIS_MODULE);
 	if (!nfnl) {
-		printk(KERN_ERR "cannot initialize nfnetlink!\n");
+		pr_err("cannot initialize nfnetlink!\n");
 		return -ENOMEM;
 	}
 
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index f900dc3..32dd241 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -43,8 +43,8 @@
 #define NFULNL_QTHRESH_DEFAULT 	100	/* 100 packets */
 #define NFULNL_COPY_RANGE_MAX	0xFFFF	/* max packet size is limited by 16-bit struct nfattr nfa_len field */
 
-#define PRINTR(x, args...)	do { if (net_ratelimit()) \
-				     printk(x, ## args); } while (0);
+#define PRINTR(level, fmt, args...)					\
+	do { if (net_ratelimit()) printk(level pr_fmt(fmt), ## args); } while (0)
 
 struct nfulnl_instance {
 	struct hlist_node hlist;	/* global list of instances */
@@ -296,8 +296,8 @@ nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size)
 	n = max(inst_size, pkt_size);
 	skb = alloc_skb(n, GFP_ATOMIC);
 	if (!skb) {
-		PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n",
-			inst_size);
+		PRINTR(KERN_ERR, "can't alloc whole buffer (%u bytes)\n",
+		       inst_size);
 
 		if (n > pkt_size) {
 			/* try to allocate only as much as we need for current
@@ -305,8 +305,8 @@ nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size)
 
 			skb = alloc_skb(pkt_size, GFP_ATOMIC);
 			if (!skb)
-				PRINTR("nfnetlink_log: can't even alloc %u "
-				       "bytes\n", pkt_size);
+				PRINTR(KERN_ERR, "can't even alloc %u bytes\n",
+				       pkt_size);
 		}
 	}
 
@@ -500,7 +500,7 @@ __build_packet_message(struct nfulnl_instance *inst,
 		int size = nla_attr_size(data_len);
 
 		if (skb_tailroom(inst->skb) < nla_total_size(data_len)) {
-			printk(KERN_WARNING "nfnetlink_log: no tailroom!\n");
+			pr_warning("no tailroom!\n");
 			goto nlmsg_failure;
 		}
 
@@ -517,7 +517,7 @@ __build_packet_message(struct nfulnl_instance *inst,
 
 nlmsg_failure:
 nla_put_failure:
-	PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
+	PRINTR(KERN_ERR, "error creating log nlmsg\n");
 	return -1;
 }
 
@@ -956,13 +956,13 @@ static int __init nfnetlink_log_init(void)
 	netlink_register_notifier(&nfulnl_rtnl_notifier);
 	status = nfnetlink_subsys_register(&nfulnl_subsys);
 	if (status < 0) {
-		printk(KERN_ERR "log: failed to create netlink socket\n");
+		pr_err("failed to create netlink socket\n");
 		goto cleanup_netlink_notifier;
 	}
 
 	status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
 	if (status < 0) {
-		printk(KERN_ERR "log: failed to register logger\n");
+		pr_err("failed to register logger\n");
 		goto cleanup_subsys;
 	}
 
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7a9dec9..d965292 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -362,7 +362,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 		int sz = nla_attr_size(data_len);
 
 		if (skb_tailroom(skb) < nla_total_size(data_len)) {
-			printk(KERN_WARNING "nf_queue: no tailroom!\n");
+			pr_warning("no tailroom!\n");
 			goto nlmsg_failure;
 		}
 
@@ -382,7 +382,7 @@ nla_put_failure:
 	if (skb)
 		kfree_skb(skb);
 	if (net_ratelimit())
-		printk(KERN_ERR "nf_queue: error creating packet message\n");
+		pr_err("error creating packet message\n");
 	return NULL;
 }
 
@@ -413,9 +413,9 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 	if (queue->queue_total >= queue->queue_maxlen) {
 		queue->queue_dropped++;
 		if (net_ratelimit())
-			  printk(KERN_WARNING "nf_queue: full at %d entries, "
-				 "dropping packets(s). Dropped: %d\n",
-				 queue->queue_total, queue->queue_dropped);
+			  pr_warning("full at %d entries, dropping packets(s). "
+				     "Dropped: %d\n",
+				     queue->queue_total, queue->queue_dropped);
 		goto err_out_free_nskb;
 	}
 
@@ -456,8 +456,7 @@ nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
 			nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
 					       diff, GFP_ATOMIC);
 			if (!nskb) {
-				printk(KERN_WARNING "nf_queue: OOM "
-				      "in mangle, dropping packet\n");
+				pr_warning("OOM in mangle, dropping packet\n");
 				return -ENOMEM;
 			}
 			kfree_skb(e->skb);
@@ -904,7 +903,7 @@ static int __init nfnetlink_queue_init(void)
 	netlink_register_notifier(&nfqnl_rtnl_notifier);
 	status = nfnetlink_subsys_register(&nfqnl_subsys);
 	if (status < 0) {
-		printk(KERN_ERR "nf_queue: failed to create netlink socket\n");
+		pr_err("failed to create netlink socket\n");
 		goto cleanup_netlink_notifier;
 	}
 
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 5934570..daf27c6 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -76,7 +76,7 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par)
 static bool connmark_tg_check(const struct xt_tgchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "cannot load conntrack support for "
+		pr_warning("cannot load conntrack support for "
 		       "proto=%u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index b54c375..c21148c 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -22,8 +22,6 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
-#define PFX "CONNSECMARK: "
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
 MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark");
@@ -91,7 +89,7 @@ static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
 
 	if (strcmp(par->table, "mangle") != 0 &&
 	    strcmp(par->table, "security") != 0) {
-		printk(KERN_INFO PFX "target only valid in the \'mangle\' "
+		pr_info("target only valid in the \'mangle\' "
 		       "or \'security\' tables, not \'%s\'.\n", par->table);
 		return false;
 	}
@@ -102,12 +100,12 @@ static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
 		break;
 
 	default:
-		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+		pr_info("invalid mode: %hu\n", info->mode);
 		return false;
 	}
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
+		pr_warning("can't load conntrack support for "
 				    "proto=%u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 74ce892..adffc77 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -65,7 +65,7 @@ static bool dscp_tg_check(const struct xt_tgchk_param *par)
 	const struct xt_DSCP_info *info = par->targinfo;
 
 	if (info->dscp > XT_DSCP_MAX) {
-		printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp);
+		pr_warning("dscp %x out of range\n", info->dscp);
 		return false;
 	}
 	return true;
diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c
index 10e789e..e4153f7 100644
--- a/net/netfilter/xt_HL.c
+++ b/net/netfilter/xt_HL.c
@@ -106,7 +106,7 @@ static bool ttl_tg_check(const struct xt_tgchk_param *par)
 	const struct ipt_TTL_info *info = par->targinfo;
 
 	if (info->mode > IPT_TTL_MAXMODE) {
-		printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
+		pr_warning("ipt_TTL: invalid or unknown Mode %u\n",
 			info->mode);
 		return false;
 	}
@@ -120,12 +120,12 @@ static bool hl_tg6_check(const struct xt_tgchk_param *par)
 	const struct ip6t_HL_info *info = par->targinfo;
 
 	if (info->mode > IP6T_HL_MAXMODE) {
-		printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
+		pr_warning("ip6t_HL: invalid or unknown Mode %u\n",
 			info->mode);
 		return false;
 	}
 	if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
-		printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
+		pr_warning("ip6t_HL: increment/decrement doesn't "
 			"make sense with value 0\n");
 		return false;
 	}
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c
index 8ff7843..8de6bf9 100644
--- a/net/netfilter/xt_LED.c
+++ b/net/netfilter/xt_LED.c
@@ -87,13 +87,13 @@ static bool led_tg_check(const struct xt_tgchk_param *par)
 	int err;
 
 	if (ledinfo->id[0] == '\0') {
-		printk(KERN_ERR KBUILD_MODNAME ": No 'id' parameter given.\n");
+		pr_err("No 'id' parameter given.\n");
 		return false;
 	}
 
 	ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL);
 	if (!ledinternal) {
-		printk(KERN_CRIT KBUILD_MODNAME ": out of memory\n");
+		pr_crit("out of memory\n");
 		return false;
 	}
 
@@ -101,11 +101,9 @@ static bool led_tg_check(const struct xt_tgchk_param *par)
 
 	err = led_trigger_register(&ledinternal->netfilter_led_trigger);
 	if (err) {
-		printk(KERN_CRIT KBUILD_MODNAME
-			": led_trigger_register() failed\n");
+		pr_crit("led_trigger_register() failed\n");
 		if (err == -EEXIST)
-			printk(KERN_ERR KBUILD_MODNAME
-				": Trigger name is already in use.\n");
+			pr_err("Trigger name is already in use.\n");
 		goto exit_alloc;
 	}
 
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index f28f6a5..0006566 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -91,12 +91,12 @@ static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
 	u32 maxid;
 
 	if (info->queues_total == 0) {
-		pr_err("NFQUEUE: number of total queues is 0\n");
+		pr_err("number of total queues is 0\n");
 		return false;
 	}
 	maxid = info->queues_total - 1 + info->queuenum;
 	if (maxid > 0xffff) {
-		pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
+		pr_err("number of queues (%u) out of range (got %u)\n",
 		       info->queues_total, maxid);
 		return false;
 	}
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 7a6f9e6..166f015 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -24,8 +24,6 @@ MODULE_DESCRIPTION("Xtables: packet security mark modification");
 MODULE_ALIAS("ipt_SECMARK");
 MODULE_ALIAS("ip6t_SECMARK");
 
-#define PFX "SECMARK: "
-
 static u8 mode;
 
 static unsigned int
@@ -59,20 +57,20 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
 	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
 	if (err) {
 		if (err == -EINVAL)
-			printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
+			pr_info("invalid SELinux context \'%s\'\n",
 			       sel->selctx);
 		return false;
 	}
 
 	if (!sel->selsid) {
-		printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
+		pr_info("unable to map SELinux context \'%s\'\n",
 		       sel->selctx);
 		return false;
 	}
 
 	err = selinux_secmark_relabel_packet_permission(sel->selsid);
 	if (err) {
-		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
+		pr_info("unable to obtain relabeling permission\n");
 		return false;
 	}
 
@@ -86,13 +84,13 @@ static bool secmark_tg_check(const struct xt_tgchk_param *par)
 
 	if (strcmp(par->table, "mangle") != 0 &&
 	    strcmp(par->table, "security") != 0) {
-		printk(KERN_INFO PFX "target only valid in the \'mangle\' "
+		pr_info("target only valid in the \'mangle\' "
 		       "or \'security\' tables, not \'%s\'.\n", par->table);
 		return false;
 	}
 
 	if (mode && mode != info->mode) {
-		printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
+		pr_info("mode already set to %hu cannot mix with "
 		       "rules for mode %hu\n", mode, info->mode);
 		return false;
 	}
@@ -104,7 +102,7 @@ static bool secmark_tg_check(const struct xt_tgchk_param *par)
 		break;
 
 	default:
-		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+		pr_info("invalid mode: %hu\n", info->mode);
 		return false;
 	}
 
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index eda64c1..dbf0896 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -67,7 +67,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 	   badly. --RR */
 	if (tcplen != tcph->doff*4) {
 		if (net_ratelimit())
-			printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n",
+			pr_err("bad length (%u bytes)\n",
 			       skb->len);
 		return -1;
 	}
@@ -75,14 +75,14 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 	if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
 		if (dst_mtu(skb_dst(skb)) <= minlen) {
 			if (net_ratelimit())
-				printk(KERN_ERR "xt_TCPMSS: "
+				pr_err(""
 				       "unknown or invalid path-MTU (%u)\n",
 				       dst_mtu(skb_dst(skb)));
 			return -1;
 		}
 		if (in_mtu <= minlen) {
 			if (net_ratelimit())
-				printk(KERN_ERR "xt_TCPMSS: unknown or "
+				pr_err("unknown or "
 				       "invalid path-MTU (%u)\n", in_mtu);
 			return -1;
 		}
@@ -246,13 +246,13 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par)
 	    (par->hook_mask & ~((1 << NF_INET_FORWARD) |
 			   (1 << NF_INET_LOCAL_OUT) |
 			   (1 << NF_INET_POST_ROUTING))) != 0) {
-		printk("xt_TCPMSS: path-MTU clamping only supported in "
-		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
+		pr_info("path-MTU clamping only supported in "
+			"FORWARD, OUTPUT and POSTROUTING hooks\n");
 		return false;
 	}
 	if (IPT_MATCH_ITERATE(e, find_syn_match))
 		return true;
-	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
+	pr_info("Only works on TCP SYN packets\n");
 	return false;
 }
 
@@ -266,13 +266,13 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par)
 	    (par->hook_mask & ~((1 << NF_INET_FORWARD) |
 			   (1 << NF_INET_LOCAL_OUT) |
 			   (1 << NF_INET_POST_ROUTING))) != 0) {
-		printk("xt_TCPMSS: path-MTU clamping only supported in "
-		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
+		pr_info("path-MTU clamping only supported in "
+			"FORWARD, OUTPUT and POSTROUTING hooks\n");
 		return false;
 	}
 	if (IP6T_MATCH_ITERATE(e, find_syn_match))
 		return true;
-	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
+	pr_info("Only works on TCP SYN packets\n");
 	return false;
 }
 #endif
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 1340c2f..c95db23 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -67,8 +67,7 @@ static bool tproxy_tg_check(const struct xt_tgchk_param *par)
 	    && !(i->invflags & IPT_INV_PROTO))
 		return true;
 
-	pr_info("xt_TPROXY: Can be used only in combination with "
-		"either -p tcp or -p udp\n");
+	pr_info("Can be used only in combination with either -p tcp or -p udp\n");
 	return false;
 }
 
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c
index 225ee3e..25daae7 100644
--- a/net/netfilter/xt_cluster.c
+++ b/net/netfilter/xt_cluster.c
@@ -136,14 +136,12 @@ static bool xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
 	struct xt_cluster_match_info *info = par->matchinfo;
 
 	if (info->total_nodes > XT_CLUSTER_NODES_MAX) {
-		printk(KERN_ERR "xt_cluster: you have exceeded the maximum "
-				"number of cluster nodes (%u > %u)\n",
-				info->total_nodes, XT_CLUSTER_NODES_MAX);
+		pr_err("you have exceeded the maximum number of cluster nodes (%u > %u)\n",
+		       info->total_nodes, XT_CLUSTER_NODES_MAX);
 		return false;
 	}
 	if (info->node_mask >= (1ULL << info->total_nodes)) {
-		printk(KERN_ERR "xt_cluster: this node mask cannot be "
-				"higher than the total number of nodes\n");
+		pr_err("this node mask cannot be higher than the total number of nodes\n");
 		return false;
 	}
 	return true;
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 955e659..c38ccd8 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -107,7 +107,7 @@ static bool connbytes_mt_check(const struct xt_mtchk_param *par)
 		return false;
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
+		pr_warning("can't load conntrack support for "
 				    "proto=%u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 6809809..1f87665 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -229,7 +229,7 @@ static bool connlimit_mt_check(const struct xt_mtchk_param *par)
 	unsigned int i;
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "cannot load conntrack support for "
+		pr_warning("cannot load conntrack support for "
 		       "address family %u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 122aa8b..186f85b 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -50,7 +50,7 @@ connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 static bool connmark_mt_check(const struct xt_mtchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "cannot load conntrack support for "
+		pr_warning("cannot load conntrack support for "
 		       "proto=%u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 6dc4652..f7f93b0 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -202,7 +202,7 @@ conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
 static bool conntrack_mt_check(const struct xt_mtchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
+		pr_warning("can't load conntrack support for "
 				    "proto=%u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 0280d3a..bb41523 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -47,7 +47,7 @@ static bool dscp_mt_check(const struct xt_mtchk_param *par)
 	const struct xt_dscp_info *info = par->matchinfo;
 
 	if (info->dscp > XT_DSCP_MAX) {
-		printk(KERN_ERR "xt_dscp: dscp %x out of range\n", info->dscp);
+		pr_err("dscp %x out of range\n", info->dscp);
 		return false;
 	}
 
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index dd16e40..20bb220 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -156,17 +156,15 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht,
 	if (ht->cfg.max && ht->count >= ht->cfg.max) {
 		/* FIXME: do something. question is what.. */
 		if (net_ratelimit())
-			printk(KERN_WARNING
-				"xt_hashlimit: max count of %u reached\n",
-				ht->cfg.max);
+			pr_warning("max count of %u reached\n",
+				   ht->cfg.max);
 		return NULL;
 	}
 
 	ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC);
 	if (!ent) {
 		if (net_ratelimit())
-			printk(KERN_ERR
-				"xt_hashlimit: can't allocate dsthash_ent\n");
+			pr_err("can't allocate dsthash_ent\n");
 		return NULL;
 	}
 	memcpy(&ent->dst, dst, sizeof(ent->dst));
@@ -205,7 +203,7 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family)
 	hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
 			sizeof(struct list_head) * size);
 	if (!hinfo) {
-		printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n");
+		pr_err("unable to create hashtable\n");
 		return -1;
 	}
 	minfo->hinfo = hinfo;
@@ -277,7 +275,7 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family)
 	hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
 	                sizeof(struct list_head) * size);
 	if (hinfo == NULL) {
-		printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n");
+		pr_err("unable to create hashtable\n");
 		return -1;
 	}
 	minfo->hinfo = hinfo;
@@ -670,7 +668,7 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
 	/* Check for overflow. */
 	if (r->cfg.burst == 0 ||
 	    user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
-		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
+		pr_err("overflow, try lower: %u/%u\n",
 		       r->cfg.avg, r->cfg.burst);
 		return false;
 	}
@@ -712,7 +710,7 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
 	if (info->cfg.burst == 0 ||
 	    user2credits(info->cfg.avg * info->cfg.burst) <
 	    user2credits(info->cfg.avg)) {
-		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
+		pr_err("overflow, try lower: %u/%u\n",
 		       info->cfg.avg, info->cfg.burst);
 		return false;
 	}
@@ -971,21 +969,19 @@ static int __init hashlimit_mt_init(void)
 					    sizeof(struct dsthash_ent), 0, 0,
 					    NULL);
 	if (!hashlimit_cachep) {
-		printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
+		pr_err("unable to create slab cache\n");
 		goto err2;
 	}
 	hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net);
 	if (!hashlimit_procdir4) {
-		printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
-				"entry\n");
+		pr_err("unable to create proc dir entry\n");
 		goto err3;
 	}
 	err = 0;
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
 	hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
 	if (!hashlimit_procdir6) {
-		printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
-				"entry\n");
+		pr_err("unable to create proc dir entry\n");
 		err = -ENOMEM;
 	}
 #endif
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 64fc7f2..4e683f6 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -59,7 +59,7 @@ static bool helper_mt_check(const struct xt_mtchk_param *par)
 	struct xt_helper_info *info = par->matchinfo;
 
 	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
+		pr_warning("can't load conntrack support for "
 				    "proto=%u\n", par->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_hl.c b/net/netfilter/xt_hl.c
index 7726154..62345e9 100644
--- a/net/netfilter/xt_hl.c
+++ b/net/netfilter/xt_hl.c
@@ -40,7 +40,7 @@ static bool ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 		case IPT_TTL_GT:
 			return ttl > info->ttl;
 		default:
-			printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
+			pr_warning("ipt_ttl: unknown mode %d\n",
 				info->mode);
 			return false;
 	}
@@ -67,7 +67,7 @@ static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
 			return ip6h->hop_limit > info->hop_limit;
 			break;
 		default:
-			printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
+			pr_warning("ip6t_hl: unknown mode %d\n",
 				info->mode);
 			return false;
 	}
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 2e8089e..ad51844 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -105,8 +105,8 @@ static bool limit_mt_check(const struct xt_mtchk_param *par)
 	/* Check for overflow. */
 	if (r->burst == 0
 	    || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
-		printk("Overflow in xt_limit, try lower: %u/%u\n",
-		       r->avg, r->burst);
+		pr_info("Overflow in xt_limit, try lower: %u/%u\n",
+			r->avg, r->burst);
 		return false;
 	}
 
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 63e1905..f50158b 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -382,13 +382,13 @@ static int __init xt_osf_init(void)
 
 	err = nfnetlink_subsys_register(&xt_osf_nfnetlink);
 	if (err < 0) {
-		printk(KERN_ERR "Failed (%d) to register OSF nsfnetlink helper.\n", err);
+		pr_err("Failed (%d) to register OSF nsfnetlink helper.\n", err);
 		goto err_out_exit;
 	}
 
 	err = xt_register_match(&xt_osf_match);
 	if (err) {
-		printk(KERN_ERR "Failed (%d) to register OS fingerprint "
+		pr_err("Failed (%d) to register OS fingerprint "
 				"matching module.\n", err);
 		goto err_out_remove;
 	}
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 8d28ca5..64186c7 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -95,7 +95,7 @@ static bool physdev_mt_check(const struct xt_mtchk_param *par)
 	     info->invert & XT_PHYSDEV_OP_BRIDGED) &&
 	    par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
 	    (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
-		printk(KERN_WARNING "physdev match: using --physdev-out in the "
+		pr_warning("physdev match: using --physdev-out in the "
 		       "OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
 		       "traffic is not supported anymore.\n");
 		if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 4cbfebd..8cf4d0f 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -133,24 +133,21 @@ static bool policy_mt_check(const struct xt_mtchk_param *par)
 	const struct xt_policy_info *info = par->matchinfo;
 
 	if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
-		printk(KERN_ERR "xt_policy: neither incoming nor "
-				"outgoing policy selected\n");
+		pr_err("neither incoming nor outgoing policy selected\n");
 		return false;
 	}
 	if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
 	    (1 << NF_INET_LOCAL_IN)) && info->flags & XT_POLICY_MATCH_OUT) {
-		printk(KERN_ERR "xt_policy: output policy not valid in "
-				"PRE_ROUTING and INPUT\n");
+		pr_err("output policy not valid in PRE_ROUTING and INPUT\n");
 		return false;
 	}
 	if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
 	    (1 << NF_INET_LOCAL_OUT)) && info->flags & XT_POLICY_MATCH_IN) {
-		printk(KERN_ERR "xt_policy: input policy not valid in "
-				"POST_ROUTING and OUTPUT\n");
+		pr_err("input policy not valid in POST_ROUTING and OUTPUT\n");
 		return false;
 	}
 	if (info->len > XT_POLICY_MAX_ELEM) {
-		printk(KERN_ERR "xt_policy: too many policy elements\n");
+		pr_err("too many policy elements\n");
 		return false;
 	}
 	return true;
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index eb0ceb8..c6635af 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -459,8 +459,8 @@ static int recent_old_seq_open(struct inode *inode, struct file *filp)
 	static bool warned_of_old;
 
 	if (unlikely(!warned_of_old)) {
-		printk(KERN_INFO KBUILD_MODNAME ": Use of /proc/net/ipt_recent"
-		       " is deprecated; use /proc/net/xt_recent.\n");
+		pr_info("Use of /proc/net/ipt_recent is deprecated; "
+			"use /proc/net/xt_recent.\n");
 		warned_of_old = true;
 	}
 	return recent_seq_open(inode, filp);
@@ -568,7 +568,7 @@ recent_mt_proc_write(struct file *file, const char __user *input,
 		add = true;
 		break;
 	default:
-		printk(KERN_INFO KBUILD_MODNAME ": Need +ip, -ip or /\n");
+		pr_info("Need +ip, -ip or /\n");
 		return -EINVAL;
 	}
 
@@ -583,8 +583,7 @@ recent_mt_proc_write(struct file *file, const char __user *input,
 	}
 
 	if (!succ) {
-		printk(KERN_INFO KBUILD_MODNAME ": illegal address written "
-		       "to procfs\n");
+		pr_info("illegal address written to procfs\n");
 		return -EINVAL;
 	}
 
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 4c946cb..3e6c3c0 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -40,7 +40,7 @@ state_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 static bool state_mt_check(const struct xt_mtchk_param *par)
 {
 	if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
-		printk(KERN_WARNING "can't load conntrack support for "
+		pr_warning("can't load conntrack support for "
 				    "proto=%u\n", par->match->family);
 		return false;
 	}
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index d8c0f8f..3cda5d8 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -62,7 +62,7 @@ static bool statistic_mt_check(const struct xt_mtchk_param *par)
 
 	info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
 	if (info->master == NULL) {
-		printk(KERN_ERR KBUILD_MODNAME ": Out of memory\n");
+		pr_err("Out of memory\n");
 		return false;
 	}
 	info->master->count = info->u.nth.count;
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index 93acaa5..e900b5e 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -224,8 +224,8 @@ static bool time_mt_check(const struct xt_mtchk_param *par)
 
 	if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
 	    info->daytime_stop > XT_TIME_MAX_DAYTIME) {
-		printk(KERN_WARNING "xt_time: invalid argument - start or "
-		       "stop time greater than 23:59:59\n");
+		pr_warning("invalid argument - start or "
+			   "stop time greater than 23:59:59\n");
 		return false;
 	}
 
@@ -246,13 +246,11 @@ static int __init time_mt_init(void)
 	int minutes = sys_tz.tz_minuteswest;
 
 	if (minutes < 0) /* east of Greenwich */
-		printk(KERN_INFO KBUILD_MODNAME
-		       ": kernel timezone is +%02d%02d\n",
-		       -minutes / 60, -minutes % 60);
+		pr_info("kernel timezone is +%02d%02d\n",
+			-minutes / 60, -minutes % 60);
 	else /* west of Greenwich */
-		printk(KERN_INFO KBUILD_MODNAME
-		       ": kernel timezone is -%02d%02d\n",
-		       minutes / 60, minutes % 60);
+		pr_info("kernel timezone is -%02d%02d\n",
+			minutes / 60, minutes % 60);
 
 	return xt_register_match(&xt_time_mt_reg);
 }
-- 
1.6.3.1.10.g659a0.dirty


^ permalink raw reply related

* [PATCH 1/2] net/netfilter/ipvs: Move #define KMSG_COMPONENT to Makefile
From: Joe Perches @ 2009-09-30 22:37 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: David S. Miller, Simon Horman, Julian Anastasov, netfilter-devel,
	coreteam, netdev, linux-kernel, lvs-devel
In-Reply-To: <cover.1254349374.git.joe@perches.com>

This centralizes the definition and removes the
replicated #defines from all files

Signed-off-by: Joe Perches <joe@perches.com>
---
 net/netfilter/ipvs/Makefile             |    3 +++
 net/netfilter/ipvs/ip_vs_app.c          |    3 ---
 net/netfilter/ipvs/ip_vs_conn.c         |    3 ---
 net/netfilter/ipvs/ip_vs_core.c         |    3 ---
 net/netfilter/ipvs/ip_vs_ctl.c          |    3 ---
 net/netfilter/ipvs/ip_vs_dh.c           |    3 ---
 net/netfilter/ipvs/ip_vs_est.c          |    3 ---
 net/netfilter/ipvs/ip_vs_ftp.c          |    3 ---
 net/netfilter/ipvs/ip_vs_lblc.c         |    3 ---
 net/netfilter/ipvs/ip_vs_lblcr.c        |    3 ---
 net/netfilter/ipvs/ip_vs_lc.c           |    3 ---
 net/netfilter/ipvs/ip_vs_nq.c           |    3 ---
 net/netfilter/ipvs/ip_vs_proto.c        |    3 ---
 net/netfilter/ipvs/ip_vs_proto_ah_esp.c |    3 ---
 net/netfilter/ipvs/ip_vs_proto_tcp.c    |    3 ---
 net/netfilter/ipvs/ip_vs_proto_udp.c    |    3 ---
 net/netfilter/ipvs/ip_vs_rr.c           |    3 ---
 net/netfilter/ipvs/ip_vs_sched.c        |    3 ---
 net/netfilter/ipvs/ip_vs_sed.c          |    3 ---
 net/netfilter/ipvs/ip_vs_sh.c           |    3 ---
 net/netfilter/ipvs/ip_vs_sync.c         |    3 ---
 net/netfilter/ipvs/ip_vs_wlc.c          |    3 ---
 net/netfilter/ipvs/ip_vs_wrr.c          |    3 ---
 net/netfilter/ipvs/ip_vs_xmit.c         |    3 ---
 24 files changed, 3 insertions(+), 69 deletions(-)

diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile
index 73a46fe..0d6f5f8 100644
--- a/net/netfilter/ipvs/Makefile
+++ b/net/netfilter/ipvs/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the IPVS modules on top of IPv4.
 #
 
+ccflags-y += -D "KMSG_COMPONENT=\"IPVS\""
+ccflags-y += -D "pr_fmt(fmt)=KMSG_COMPONENT \": \" fmt"
+
 # IPVS transport protocol load balancing support
 ip_vs_proto-objs-y :=
 ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 3c7e427..a5283d8 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -18,9 +18,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 27c30cf..b62fdf6 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -22,9 +22,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/net.h>
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index b95699f..b3a103f 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -24,9 +24,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ip.h>
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 446e9bd..9c19485 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -18,9 +18,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index fe3e188..a91ce7b 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -35,9 +35,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 702b53c..1fa96bd 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -12,9 +12,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 33e2c79..e1c9c03 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -22,9 +22,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index c1757f3..8512305 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -39,9 +39,6 @@
  * me to write this module.
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 715b57f..4412b45 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -37,9 +37,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
index 4f69db1..e906763 100644
--- a/net/netfilter/ipvs/ip_vs_lc.c
+++ b/net/netfilter/ipvs/ip_vs_lc.c
@@ -14,9 +14,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
index c413e18..4fbaf1d 100644
--- a/net/netfilter/ipvs/ip_vs_nq.c
+++ b/net/netfilter/ipvs/ip_vs_nq.c
@@ -31,9 +31,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 3e76716..b61e4b6 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -13,9 +13,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index c30b43c..b4249f2 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -10,9 +10,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/module.h>
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 91d28e0..3ca6278 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -13,9 +13,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/kernel.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>                  /* for tcphdr */
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index e7a6885..61aec0c 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -13,9 +13,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
index e210f37..5857da9 100644
--- a/net/netfilter/ipvs/ip_vs_rr.c
+++ b/net/netfilter/ipvs/ip_vs_rr.c
@@ -19,9 +19,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index bbc1ac7..cd9efc9 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -17,9 +17,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
index 1ab75a9..2b9d2c0 100644
--- a/net/netfilter/ipvs/ip_vs_sed.c
+++ b/net/netfilter/ipvs/ip_vs_sed.c
@@ -35,9 +35,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 8e6cfd3..b5cabba 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -32,9 +32,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/ip.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index e177f0d..6919cda 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -17,9 +17,6 @@
  *	Justin Ossevoort	:	Fix endian problem on sync message size.
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/inetdevice.h>
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
index bbddfdb..8e94256 100644
--- a/net/netfilter/ipvs/ip_vs_wlc.c
+++ b/net/netfilter/ipvs/ip_vs_wlc.c
@@ -19,9 +19,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
index 6182e8e..ab97dc1 100644
--- a/net/netfilter/ipvs/ip_vs_wrr.c
+++ b/net/netfilter/ipvs/ip_vs_wrr.c
@@ -18,9 +18,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/net.h>
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 30b3189..c23c0a1 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -13,9 +13,6 @@
  *
  */
 
-#define KMSG_COMPONENT "IPVS"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
 #include <linux/kernel.h>
 #include <linux/tcp.h>                  /* for tcphdr */
 #include <net/ip.h>
-- 
1.6.3.1.10.g659a0.dirty


^ permalink raw reply related

* [PATCH 0/2] net/netfilter: Makefile and pr_<level>
From: Joe Perches @ 2009-09-30 22:37 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: David S. Miller, Simon Horman, Julian Anastasov, netfilter-devel,
	coreteam, netdev, linux-kernel, lvs-devel

Standardize mechanism to #define KMSG_COMPONENT by
moving it to Makefile and cleanup and standardize
printks.  Corrected a few error message typos along
the way.

Joe Perches (2):
  net/netfilter/ipvs: Move #define KMSG_COMPONENT to Makefile
  net/netfilter: use pr_<level> consistently

 net/netfilter/Makefile                  |    2 +
 net/netfilter/ipvs/Makefile             |    3 +
 net/netfilter/ipvs/ip_vs_app.c          |    3 -
 net/netfilter/ipvs/ip_vs_conn.c         |    3 -
 net/netfilter/ipvs/ip_vs_core.c         |    3 -
 net/netfilter/ipvs/ip_vs_ctl.c          |    3 -
 net/netfilter/ipvs/ip_vs_dh.c           |    3 -
 net/netfilter/ipvs/ip_vs_est.c          |    3 -
 net/netfilter/ipvs/ip_vs_ftp.c          |    3 -
 net/netfilter/ipvs/ip_vs_lblc.c         |    3 -
 net/netfilter/ipvs/ip_vs_lblcr.c        |    3 -
 net/netfilter/ipvs/ip_vs_lc.c           |    3 -
 net/netfilter/ipvs/ip_vs_nq.c           |    3 -
 net/netfilter/ipvs/ip_vs_proto.c        |    3 -
 net/netfilter/ipvs/ip_vs_proto_ah_esp.c |    3 -
 net/netfilter/ipvs/ip_vs_proto_tcp.c    |    3 -
 net/netfilter/ipvs/ip_vs_proto_udp.c    |    3 -
 net/netfilter/ipvs/ip_vs_rr.c           |    3 -
 net/netfilter/ipvs/ip_vs_sched.c        |    3 -
 net/netfilter/ipvs/ip_vs_sed.c          |    3 -
 net/netfilter/ipvs/ip_vs_sh.c           |    3 -
 net/netfilter/ipvs/ip_vs_sync.c         |    3 -
 net/netfilter/ipvs/ip_vs_wlc.c          |    3 -
 net/netfilter/ipvs/ip_vs_wrr.c          |    3 -
 net/netfilter/ipvs/ip_vs_xmit.c         |    3 -
 net/netfilter/nf_conntrack_acct.c       |   12 ++--
 net/netfilter/nf_conntrack_amanda.c     |    2 +-
 net/netfilter/nf_conntrack_core.c       |   35 ++++-----
 net/netfilter/nf_conntrack_ecache.c     |    5 +-
 net/netfilter/nf_conntrack_expect.c     |    3 +-
 net/netfilter/nf_conntrack_ftp.c        |   31 ++++-----
 net/netfilter/nf_conntrack_h323_main.c  |  114 +++++++++++++++---------------
 net/netfilter/nf_conntrack_irc.c        |   10 +--
 net/netfilter/nf_conntrack_netlink.c    |   12 ++--
 net/netfilter/nf_conntrack_proto_gre.c  |    4 +-
 net/netfilter/nf_conntrack_proto_sctp.c |    9 +--
 net/netfilter/nf_conntrack_proto_tcp.c  |    4 +-
 net/netfilter/nf_conntrack_sane.c       |   17 ++---
 net/netfilter/nf_conntrack_sip.c        |    5 +-
 net/netfilter/nf_conntrack_standalone.c |    2 +-
 net/netfilter/nf_conntrack_tftp.c       |    3 +-
 net/netfilter/nfnetlink.c               |    6 +-
 net/netfilter/nfnetlink_log.c           |   20 +++---
 net/netfilter/nfnetlink_queue.c         |   15 ++--
 net/netfilter/xt_CONNMARK.c             |    2 +-
 net/netfilter/xt_CONNSECMARK.c          |    8 +--
 net/netfilter/xt_DSCP.c                 |    2 +-
 net/netfilter/xt_HL.c                   |    6 +-
 net/netfilter/xt_LED.c                  |   10 +--
 net/netfilter/xt_NFQUEUE.c              |    4 +-
 net/netfilter/xt_SECMARK.c              |   14 ++--
 net/netfilter/xt_TCPMSS.c               |   18 +++---
 net/netfilter/xt_TPROXY.c               |    3 +-
 net/netfilter/xt_cluster.c              |    8 +--
 net/netfilter/xt_connbytes.c            |    2 +-
 net/netfilter/xt_connlimit.c            |    2 +-
 net/netfilter/xt_connmark.c             |    2 +-
 net/netfilter/xt_conntrack.c            |    2 +-
 net/netfilter/xt_dscp.c                 |    2 +-
 net/netfilter/xt_hashlimit.c            |   24 +++----
 net/netfilter/xt_helper.c               |    2 +-
 net/netfilter/xt_hl.c                   |    4 +-
 net/netfilter/xt_limit.c                |    4 +-
 net/netfilter/xt_osf.c                  |    4 +-
 net/netfilter/xt_physdev.c              |    2 +-
 net/netfilter/xt_policy.c               |   11 +--
 net/netfilter/xt_recent.c               |    9 +--
 net/netfilter/xt_state.c                |    2 +-
 net/netfilter/xt_statistic.c            |    2 +-
 net/netfilter/xt_time.c                 |   14 ++--
 70 files changed, 224 insertions(+), 322 deletions(-)


^ permalink raw reply

* [net-2.6 PATCH 5/5] ixgbe: Remove ATR computation for UDP traffic
From: Jeff Kirsher @ 2009-09-30 22:08 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20090930220705.27479.62694.stgit@localhost.localdomain>

From: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>

ATR support for UDP on 82599 needs to be redesigned, since the
current model doesn't make much sense.  The fallout from having
it in though is it causes all UDP traffic to still compute the
ATR hashes on transmit, which are useless.  This removal will
return upwards of 10% of relative computational overhead in
forwarding tests.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_main.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 9609673..1cbc6a3 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5091,7 +5091,6 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
 	/* Right now, we support IPv4 only */
 	struct ixgbe_atr_input atr_input;
 	struct tcphdr *th;
-	struct udphdr *uh;
 	struct iphdr *iph = ip_hdr(skb);
 	struct ethhdr *eth = (struct ethhdr *)skb->data;
 	u16 vlan_id, src_port, dst_port, flex_bytes;
@@ -5105,12 +5104,6 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
 		dst_port = th->dest;
 		l4type |= IXGBE_ATR_L4TYPE_TCP;
 		/* l4type IPv4 type is 0, no need to assign */
-	} else if(iph->protocol == IPPROTO_UDP) {
-		uh = udp_hdr(skb);
-		src_port = uh->source;
-		dst_port = uh->dest;
-		l4type |= IXGBE_ATR_L4TYPE_UDP;
-		/* l4type IPv4 type is 0, no need to assign */
 	} else {
 		/* Unsupported L4 header, just bail here */
 		return;


^ permalink raw reply related

* [net-2.6 PATCH 4/5] ixgbe patch to provide NIC's tx/rx counters via ethtool
From: Jeff Kirsher @ 2009-09-30 22:08 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Ben Greear, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20090930220705.27479.62694.stgit@localhost.localdomain>

From: Ben Greear <greearb@candelatech.com>

When LRO is enabled, the received packet and byte counters represent the
LRO'd packets, not the packets/bytes on the wire.  The Intel 82599 NIC has
registers that keep count of the physical packets.  Add these counters to
the ethtool stats.  The byte counters are 36-bit, but the high 4 bits were
being ignored in the 2.6.31 ixgbe driver:  Read those as well to allow
longer time between polling the stats to detect wraps.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_ethtool.c |    4 ++++
 drivers/net/ixgbe/ixgbe_main.c    |    7 +++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 53b0a66..fa314cb 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -53,6 +53,10 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
 	{"tx_packets", IXGBE_STAT(net_stats.tx_packets)},
 	{"rx_bytes", IXGBE_STAT(net_stats.rx_bytes)},
 	{"tx_bytes", IXGBE_STAT(net_stats.tx_bytes)},
+	{"rx_pkts_nic", IXGBE_STAT(stats.gprc)},
+	{"tx_pkts_nic", IXGBE_STAT(stats.gptc)},
+	{"rx_bytes_nic", IXGBE_STAT(stats.gorc)},
+	{"tx_bytes_nic", IXGBE_STAT(stats.gotc)},
 	{"lsc_int", IXGBE_STAT(lsc_int)},
 	{"tx_busy", IXGBE_STAT(tx_busy)},
 	{"non_eop_descs", IXGBE_STAT(non_eop_descs)},
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index c198183..9609673 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -4449,10 +4449,13 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
 
 	/* 82598 hardware only has a 32 bit counter in the high register */
 	if (hw->mac.type == ixgbe_mac_82599EB) {
+		u64 tmp;
 		adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
-		IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */
+		tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF; /* 4 high bits of GORC */
+		adapter->stats.gorc += (tmp << 32);
 		adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
-		IXGBE_READ_REG(hw, IXGBE_GOTCH); /* to clear */
+		tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF; /* 4 high bits of GOTC */
+		adapter->stats.gotc += (tmp << 32);
 		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL);
 		IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
 		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);


^ permalink raw reply related

* [net-2.6 PATCH 3/5] ixgbe: Bump driver version number
From: Jeff Kirsher @ 2009-09-30 22:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20090930220705.27479.62694.stgit@localhost.localdomain>

From: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>

A number of changes have gone in since the last version bump.  Bump
it to reflect the changes.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index fe52736..c198183 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -49,7 +49,7 @@ char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
                               "Intel(R) 10 Gigabit PCI Express Network Driver";
 
-#define DRV_VERSION "2.0.37-k2"
+#define DRV_VERSION "2.0.44-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
 


^ permalink raw reply related

* [net-2.6 PATCH 2/5] ixgbe: Fix backplane flow control autoneg
From: Jeff Kirsher @ 2009-09-30 22:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20090930220705.27479.62694.stgit@localhost.localdomain>

From: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>

Backplane flow control autonegotiation is currently broken for
ixgbe devices.  This patch fixes the flow control issues
with clause 37 autoneg.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_82598.c  |    2 
 drivers/net/ixgbe/ixgbe_common.c |  228 ++++++++++++++++++++++++++++++--------
 drivers/net/ixgbe/ixgbe_type.h   |    9 ++
 3 files changed, 187 insertions(+), 52 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 56b12f3..e2d5343 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -425,7 +425,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
 #endif /* CONFIG_DCB */
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = -IXGBE_ERR_CONFIG;
+		ret_val = IXGBE_ERR_CONFIG;
 		goto out;
 		break;
 	}
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 6621e17..143b0fc 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1663,7 +1663,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
 #endif /* CONFIG_DCB */
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = -IXGBE_ERR_CONFIG;
+		ret_val = IXGBE_ERR_CONFIG;
 		goto out;
 		break;
 	}
@@ -1734,75 +1734,140 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 	s32 ret_val = 0;
 	ixgbe_link_speed speed;
 	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+	u32 links2, anlp1_reg, autoc_reg, links;
 	bool link_up;
 
 	/*
 	 * AN should have completed when the cable was plugged in.
 	 * Look for reasons to bail out.  Bail out if:
 	 * - FC autoneg is disabled, or if
-	 * - we don't have multispeed fiber, or if
-	 * - we're not running at 1G, or if
-	 * - link is not up, or if
-	 * - link is up but AN did not complete, or if
-	 * - link is up and AN completed but timed out
+	 * - link is not up.
 	 *
-	 * Since we're being called from an LSC, link is already know to be up.
+	 * Since we're being called from an LSC, link is already known to be up.
 	 * So use link_up_wait_to_complete=false.
 	 */
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
-	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-
-	if (hw->fc.disable_fc_autoneg ||
-	    !hw->phy.multispeed_fiber ||
-	    (speed != IXGBE_LINK_SPEED_1GB_FULL) ||
-	    !link_up ||
-	    ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
-	    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+
+	if (hw->fc.disable_fc_autoneg || (!link_up)) {
 		hw->fc.fc_was_autonegged = false;
 		hw->fc.current_mode = hw->fc.requested_mode;
-		hw_dbg(hw, "Autoneg FC was skipped.\n");
 		goto out;
 	}
 
 	/*
+	 * On backplane, bail out if
+	 * - backplane autoneg was not completed, or if
+	 * - link partner is not AN enabled
+	 */
+	if (hw->phy.media_type == ixgbe_media_type_backplane) {
+		links = IXGBE_READ_REG(hw, IXGBE_LINKS);
+		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+		if (((links & IXGBE_LINKS_KX_AN_COMP) == 0) ||
+		    ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)) {
+			hw->fc.fc_was_autonegged = false;
+			hw->fc.current_mode = hw->fc.requested_mode;
+			goto out;
+		}
+	}
+
+	/*
+	 * On multispeed fiber at 1g, bail out if
+	 * - link is up but AN did not complete, or if
+	 * - link is up and AN completed but timed out
+	 */
+	if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
+		linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+		if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+		    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+			hw->fc.fc_was_autonegged = false;
+			hw->fc.current_mode = hw->fc.requested_mode;
+			goto out;
+		}
+	}
+
+	/*
 	 * Read the AN advertisement and LP ability registers and resolve
 	 * local flow control settings accordingly
 	 */
-	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
-	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
-	if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+	if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
+	    (hw->phy.media_type != ixgbe_media_type_backplane)) {
+		pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+		pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+		if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+		    (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+			/*
+			 * Now we need to check if the user selected Rx ONLY
+			 * of pause frames.  In this case, we had to advertise
+			 * FULL flow control because we could not advertise RX
+			 * ONLY. Hence, we must now check to see if we need to
+			 * turn OFF the TRANSMISSION of PAUSE frames.
+			 */
+			if (hw->fc.requested_mode == ixgbe_fc_full) {
+				hw->fc.current_mode = ixgbe_fc_full;
+				hw_dbg(hw, "Flow Control = FULL.\n");
+			} else {
+				hw->fc.current_mode = ixgbe_fc_rx_pause;
+				hw_dbg(hw, "Flow Control=RX PAUSE only\n");
+			}
+		} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+			   (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+			hw->fc.current_mode = ixgbe_fc_tx_pause;
+			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+		} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+			   !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+			hw->fc.current_mode = ixgbe_fc_rx_pause;
+			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+		} else {
+			hw->fc.current_mode = ixgbe_fc_none;
+			hw_dbg(hw, "Flow Control = NONE.\n");
+		}
+	}
+
+	if (hw->phy.media_type == ixgbe_media_type_backplane) {
 		/*
-		 * Now we need to check if the user selected Rx ONLY
-		 * of pause frames.  In this case, we had to advertise
-		 * FULL flow control because we could not advertise RX
-		 * ONLY. Hence, we must now check to see if we need to
-		 * turn OFF the TRANSMISSION of PAUSE frames.
+		 * Read the 10g AN autoc and LP ability registers and resolve
+		 * local flow control settings accordingly
 		 */
-		if (hw->fc.requested_mode == ixgbe_fc_full) {
-			hw->fc.current_mode = ixgbe_fc_full;
-			hw_dbg(hw, "Flow Control = FULL.\n");
-		} else {
+		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+
+		if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+		    (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
+			/*
+			 * Now we need to check if the user selected Rx ONLY
+			 * of pause frames.  In this case, we had to advertise
+			 * FULL flow control because we could not advertise RX
+			 * ONLY. Hence, we must now check to see if we need to
+			 * turn OFF the TRANSMISSION of PAUSE frames.
+			 */
+			if (hw->fc.requested_mode == ixgbe_fc_full) {
+				hw->fc.current_mode = ixgbe_fc_full;
+				hw_dbg(hw, "Flow Control = FULL.\n");
+			} else {
+				hw->fc.current_mode = ixgbe_fc_rx_pause;
+				hw_dbg(hw, "Flow Control=RX PAUSE only\n");
+			}
+		} else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+			   (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
+			hw->fc.current_mode = ixgbe_fc_tx_pause;
+			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+		} else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+			   !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
 			hw->fc.current_mode = ixgbe_fc_rx_pause;
 			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+		} else {
+			hw->fc.current_mode = ixgbe_fc_none;
+			hw_dbg(hw, "Flow Control = NONE.\n");
 		}
-	} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-		   (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-		hw->fc.current_mode = ixgbe_fc_tx_pause;
-		hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
-	} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-		   !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-		hw->fc.current_mode = ixgbe_fc_rx_pause;
-		hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
-	} else {
-		hw->fc.current_mode = ixgbe_fc_none;
-		hw_dbg(hw, "Flow Control = NONE.\n");
 	}
-
 	/* Record that current_mode is the result of a successful autoneg */
 	hw->fc.fc_was_autonegged = true;
 
@@ -1919,7 +1984,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 #endif /* CONFIG_DCB */
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = -IXGBE_ERR_CONFIG;
+		ret_val = IXGBE_ERR_CONFIG;
 		goto out;
 		break;
 	}
@@ -1927,9 +1992,6 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
 	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
 
-	/* Enable and restart autoneg to inform the link partner */
-	reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
-
 	/* Disable AN timeout */
 	if (hw->fc.strict_ieee)
 		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
@@ -1937,6 +1999,70 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
 	hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
 
+	/*
+	 * Set up the 10G flow control advertisement registers so the HW
+	 * can do fc autoneg once the cable is plugged in.  If we end up
+	 * using 1g instead, this is harmless.
+	 */
+	reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+	/*
+	 * The possible values of fc.requested_mode are:
+	 * 0: Flow control is completely disabled
+	 * 1: Rx flow control is enabled (we can receive pause frames,
+	 *    but not send pause frames).
+	 * 2: Tx flow control is enabled (we can send pause frames but
+	 *    we do not support receiving pause frames).
+	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
+	 * other: Invalid.
+	 */
+	switch (hw->fc.requested_mode) {
+	case ixgbe_fc_none:
+		/* Flow control completely disabled by software override. */
+		reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+		break;
+	case ixgbe_fc_rx_pause:
+		/*
+		 * Rx Flow control is enabled and Tx Flow control is
+		 * disabled by software override. Since there really
+		 * isn't a way to advertise that we are capable of RX
+		 * Pause ONLY, we will advertise that we support both
+		 * symmetric and asymmetric Rx PAUSE.  Later, we will
+		 * disable the adapter's ability to send PAUSE frames.
+		 */
+		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+		break;
+	case ixgbe_fc_tx_pause:
+		/*
+		 * Tx Flow control is enabled, and Rx Flow control is
+		 * disabled by software override.
+		 */
+		reg |= (IXGBE_AUTOC_ASM_PAUSE);
+		reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
+		break;
+	case ixgbe_fc_full:
+		/* Flow control (both Rx and Tx) is enabled by SW override. */
+		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+		break;
+#ifdef CONFIG_DCB
+	case ixgbe_fc_pfc:
+		goto out;
+		break;
+#endif /* CONFIG_DCB */
+	default:
+		hw_dbg(hw, "Flow control param set incorrectly\n");
+		ret_val = IXGBE_ERR_CONFIG;
+		goto out;
+		break;
+	}
+	/*
+	 * AUTOC restart handles negotiation of 1G and 10G. There is
+	 * no need to set the PCS1GCTL register.
+	 */
+	reg |= IXGBE_AUTOC_AN_RESTART;
+	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
+	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+
 out:
 	return ret_val;
 }
@@ -2000,7 +2126,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 
 	while (timeout) {
 		if (ixgbe_get_eeprom_semaphore(hw))
-			return -IXGBE_ERR_SWFW_SYNC;
+			return IXGBE_ERR_SWFW_SYNC;
 
 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
 		if (!(gssr & (fwmask | swmask)))
@@ -2017,7 +2143,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 
 	if (!timeout) {
 		hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n");
-		return -IXGBE_ERR_SWFW_SYNC;
+		return IXGBE_ERR_SWFW_SYNC;
 	}
 
 	gssr |= swmask;
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 8761d78..7c93e92 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1336,6 +1336,8 @@
 #define IXGBE_AUTOC_KX4_SUPP    0x80000000
 #define IXGBE_AUTOC_KX_SUPP     0x40000000
 #define IXGBE_AUTOC_PAUSE       0x30000000
+#define IXGBE_AUTOC_ASM_PAUSE   0x20000000
+#define IXGBE_AUTOC_SYM_PAUSE   0x10000000
 #define IXGBE_AUTOC_RF          0x08000000
 #define IXGBE_AUTOC_PD_TMR      0x06000000
 #define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000
@@ -1404,6 +1406,8 @@
 #define IXGBE_LINK_UP_TIME      90 /* 9.0 Seconds */
 #define IXGBE_AUTO_NEG_TIME     45 /* 4.5 Seconds */
 
+#define IXGBE_LINKS2_AN_SUPPORTED   0x00000040
+
 /* PCS1GLSTA Bit Masks */
 #define IXGBE_PCS1GLSTA_LINK_OK         1
 #define IXGBE_PCS1GLSTA_SYNK_OK         0x10
@@ -1424,6 +1428,11 @@
 #define IXGBE_PCS1GLCTL_AN_ENABLE       0x10000
 #define IXGBE_PCS1GLCTL_AN_RESTART      0x20000
 
+/* ANLP1 Bit Masks */
+#define IXGBE_ANLP1_PAUSE               0x0C00
+#define IXGBE_ANLP1_SYM_PAUSE           0x0400
+#define IXGBE_ANLP1_ASM_PAUSE           0x0800
+
 /* SW Semaphore Register bitmasks */
 #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
 #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */


^ permalink raw reply related

* [net-2.6 PATCH 1/5] ixgbe: Fix disabling of relaxed ordering with Tx DCA
From: Jeff Kirsher @ 2009-09-30 22:07 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher

From: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>

82599 has a different register offset for the Tx DCA control registers.
We disable relaxed ordering of the descriptor writebacks for Tx head
writeback, but didn't disable it properly for 82599.  However, this
shouldn't be a visible issue, since ixgbe doesn't use Tx head writeback.
This patch just makes sure we're not doing blind writes to offsets we
don't expect.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_main.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index c407bd9..fe52736 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1885,12 +1885,29 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
 		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
 		adapter->tx_ring[i].head = IXGBE_TDH(j);
 		adapter->tx_ring[i].tail = IXGBE_TDT(j);
-		/* Disable Tx Head Writeback RO bit, since this hoses
+		/*
+		 * Disable Tx Head Writeback RO bit, since this hoses
 		 * bookkeeping if things aren't delivered in order.
 		 */
-		txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
+		switch (hw->mac.type) {
+		case ixgbe_mac_82598EB:
+			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
+			break;
+		case ixgbe_mac_82599EB:
+		default:
+			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
+			break;
+		}
 		txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
-		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
+		switch (hw->mac.type) {
+		case ixgbe_mac_82598EB:
+			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
+			break;
+		case ixgbe_mac_82599EB:
+		default:
+			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
+			break;
+		}
 	}
 	if (hw->mac.type == ixgbe_mac_82599EB) {
 		/* We enable 8 traffic classes, DCB only */


^ permalink raw reply related

* Re: r8169 chips on some Intel D945GSEJT boards fail to work after PXE boot
From: Francois Romieu @ 2009-09-30 22:07 UTC (permalink / raw)
  To: Simon Farnsworth; +Cc: netdev
In-Reply-To: <4ABB5435.6040609@onelan.com>

Simon Farnsworth <simon.farnsworth@onelan.com> :
[...]
> We've tried this, and we've tried 2GB and 1GB modules; the failure to
> boot sticks with the board, not with the memory module. On my most
> recent attempt, the failing board isn't showing a correctable error
> status, so I've not yet tried your patch, on the assumption that it just
> clears the error status.
> 
> Is my assumption wrong? If not, is there anything else I can do that
> would help you diagnose this?

Try this against 2.6.31 or latest -rc.


diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 50c6a3c..74488a6 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -115,7 +115,9 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_22 = 0x16, // 8168C
 	RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP
 	RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
-	RTL_GIGA_MAC_VER_25 = 0x19  // 8168D
+	RTL_GIGA_MAC_VER_25 = 0x19, // 8168D
+	RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
+	RTL_GIGA_MAC_VER_27 = 0x1b  // 8168DP
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -150,7 +152,9 @@ static const struct {
 	_R("RTL8168c/8111c",	RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
 	_R("RTL8168cp/8111cp",	RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
 	_R("RTL8168cp/8111cp",	RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
-	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_25, 0xff7e1880)  // PCI-E
+	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
+	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
+	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_27, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -253,6 +257,13 @@ enum rtl8168_8101_registers {
 	DBG_REG			= 0xd1,
 #define	FIX_NAK_1			(1 << 4)
 #define	FIX_NAK_2			(1 << 3)
+	EFUSEAR			= 0xdc,
+#define	EFUSEAR_FLAG			0x80000000
+#define	EFUSEAR_WRITE_CMD		0x80000000
+#define	EFUSEAR_READ_CMD		0x00000000
+#define	EFUSEAR_REG_MASK		0x03ff
+#define	EFUSEAR_REG_SHIFT		8
+#define	EFUSEAR_DATA_MASK		0xff
 };
 
 enum rtl_register_content {
@@ -568,6 +579,14 @@ static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
 	mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
 }
 
+static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m)
+{
+	int val;
+
+	val = mdio_read(ioaddr, reg_addr);
+	mdio_write(ioaddr, reg_addr, (val | p) & ~m);
+}
+
 static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
 			   int val)
 {
@@ -651,6 +670,24 @@ static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
 	return value;
 }
 
+static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
+{
+	u8 value = 0xff;
+	unsigned int i;
+
+	RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
+
+	for (i = 0; i < 300; i++) {
+		if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) {
+			value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK;
+			break;
+		}
+		udelay(100);
+	}
+
+	return value;
+}
+
 static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
 {
 	RTL_W16(IntrMask, 0x0000);
@@ -1243,7 +1280,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		int mac_version;
 	} mac_info[] = {
 		/* 8168D family. */
-		{ 0x7c800000, 0x28000000,	RTL_GIGA_MAC_VER_25 },
+		{ 0x7cf00000, 0x28300000,	RTL_GIGA_MAC_VER_26 },
+		{ 0x7cf00000, 0x28100000,	RTL_GIGA_MAC_VER_25 },
+		{ 0x7c800000, 0x28800000,	RTL_GIGA_MAC_VER_27 },
+		{ 0x7c800000, 0x28000000,	RTL_GIGA_MAC_VER_26 },
 
 		/* 8168C family. */
 		{ 0x7cf00000, 0x3ca00000,	RTL_GIGA_MAC_VER_24 },
@@ -1648,74 +1688,903 @@ static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
 	rtl8168c_3_hw_phy_config(ioaddr);
 }
 
-static void rtl8168d_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
 {
 	struct phy_reg phy_reg_init_0[] = {
 		{ 0x1f, 0x0001 },
-		{ 0x09, 0x2770 },
-		{ 0x08, 0x04d0 },
-		{ 0x0b, 0xad15 },
-		{ 0x0c, 0x5bf0 },
-		{ 0x1c, 0xf101 },
+		{ 0x06, 0x4064 },
+		{ 0x07, 0x2863 },
+		{ 0x08, 0x059c },
+		{ 0x09, 0x26b4 },
+		{ 0x0a, 0x6a19 },
+		{ 0x0b, 0xdcc8 },
+		{ 0x10, 0xf06d },
+		{ 0x14, 0x7f68 },
+		{ 0x18, 0x7fd9 },
+		{ 0x1c, 0xf0ff },
+		{ 0x1d, 0x3d9c },
 		{ 0x1f, 0x0003 },
-		{ 0x14, 0x94d7 },
-		{ 0x12, 0xf4d6 },
-		{ 0x09, 0xca0f },
-		{ 0x1f, 0x0002 },
-		{ 0x0b, 0x0b10 },
-		{ 0x0c, 0xd1f7 },
-		{ 0x1f, 0x0002 },
-		{ 0x06, 0x5461 },
+		{ 0x12, 0xf49f },
+		{ 0x13, 0x070b },
+		{ 0x1a, 0x05ad },
+		{ 0x14, 0x94c0 }
+	};
+	struct phy_reg phy_reg_init_1[] = {
 		{ 0x1f, 0x0002 },
-		{ 0x05, 0x6662 },
+		{ 0x06, 0x5561 },
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8332 },
+		{ 0x06, 0x5561 }
+	};
+	struct phy_reg phy_reg_init_2[] = {
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0xffc2 },
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8000 },
+		{ 0x06, 0xf8f9 },
+		{ 0x06, 0xfaef },
+		{ 0x06, 0x59ee },
+		{ 0x06, 0xf8ea },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0xf8eb },
+		{ 0x06, 0x00e0 },
+		{ 0x06, 0xf87c },
+		{ 0x06, 0xe1f8 },
+		{ 0x06, 0x7d59 },
+		{ 0x06, 0x0fef },
+		{ 0x06, 0x0139 },
+		{ 0x06, 0x029e },
+		{ 0x06, 0x06ef },
+		{ 0x06, 0x1039 },
+		{ 0x06, 0x089f },
+		{ 0x06, 0x2aee },
+		{ 0x06, 0xf8ea },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0xf8eb },
+		{ 0x06, 0x01e0 },
+		{ 0x06, 0xf87c },
+		{ 0x06, 0xe1f8 },
+		{ 0x06, 0x7d58 },
+		{ 0x06, 0x409e },
+		{ 0x06, 0x0f39 },
+		{ 0x06, 0x46aa },
+		{ 0x06, 0x0bbf },
+		{ 0x06, 0x8290 },
+		{ 0x06, 0xd682 },
+		{ 0x06, 0x9802 },
+		{ 0x06, 0x014f },
+		{ 0x06, 0xae09 },
+		{ 0x06, 0xbf82 },
+		{ 0x06, 0x98d6 },
+		{ 0x06, 0x82a0 },
+		{ 0x06, 0x0201 },
+		{ 0x06, 0x4fef },
+		{ 0x06, 0x95fe },
+		{ 0x06, 0xfdfc },
+		{ 0x06, 0x05f8 },
+		{ 0x06, 0xf9fa },
+		{ 0x06, 0xeef8 },
+		{ 0x06, 0xea00 },
+		{ 0x06, 0xeef8 },
+		{ 0x06, 0xeb00 },
+		{ 0x06, 0xe2f8 },
+		{ 0x06, 0x7ce3 },
+		{ 0x06, 0xf87d },
+		{ 0x06, 0xa511 },
+		{ 0x06, 0x1112 },
+		{ 0x06, 0xd240 },
+		{ 0x06, 0xd644 },
+		{ 0x06, 0x4402 },
+		{ 0x06, 0x8217 },
+		{ 0x06, 0xd2a0 },
+		{ 0x06, 0xd6aa },
+		{ 0x06, 0xaa02 },
+		{ 0x06, 0x8217 },
+		{ 0x06, 0xae0f },
+		{ 0x06, 0xa544 },
+		{ 0x06, 0x4402 },
+		{ 0x06, 0xae4d },
+		{ 0x06, 0xa5aa },
+		{ 0x06, 0xaa02 },
+		{ 0x06, 0xae47 },
+		{ 0x06, 0xaf82 },
+		{ 0x06, 0x13ee },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0x834d },
+		{ 0x06, 0x0fee },
+		{ 0x06, 0x834c },
+		{ 0x06, 0x0fee },
+		{ 0x06, 0x834f },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0x8351 },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0x834a },
+		{ 0x06, 0xffee },
+		{ 0x06, 0x834b },
+		{ 0x06, 0xffe0 },
+		{ 0x06, 0x8330 },
+		{ 0x06, 0xe183 },
+		{ 0x06, 0x3158 },
+		{ 0x06, 0xfee4 },
+		{ 0x06, 0xf88a },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x8be0 },
+		{ 0x06, 0x8332 },
+		{ 0x06, 0xe183 },
+		{ 0x06, 0x3359 },
+		{ 0x06, 0x0fe2 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0x0c24 },
+		{ 0x06, 0x5af0 },
+		{ 0x06, 0x1e12 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x8ce5 },
+		{ 0x06, 0xf88d },
+		{ 0x06, 0xaf82 },
+		{ 0x06, 0x13e0 },
+		{ 0x06, 0x834f },
+		{ 0x06, 0x10e4 },
+		{ 0x06, 0x834f },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x009f },
+		{ 0x06, 0x0ae0 },
+		{ 0x06, 0x834f },
+		{ 0x06, 0xa010 },
+		{ 0x06, 0xa5ee },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x01e0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7805 },
+		{ 0x06, 0x9e9a },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x049e },
+		{ 0x06, 0x10e0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7803 },
+		{ 0x06, 0x9e0f },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x019e },
+		{ 0x06, 0x05ae },
+		{ 0x06, 0x0caf },
+		{ 0x06, 0x81f8 },
+		{ 0x06, 0xaf81 },
+		{ 0x06, 0xa3af },
+		{ 0x06, 0x81dc },
+		{ 0x06, 0xaf82 },
+		{ 0x06, 0x13ee },
+		{ 0x06, 0x8348 },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0x8349 },
+		{ 0x06, 0x00e0 },
+		{ 0x06, 0x8351 },
+		{ 0x06, 0x10e4 },
+		{ 0x06, 0x8351 },
+		{ 0x06, 0x5801 },
+		{ 0x06, 0x9fea },
+		{ 0x06, 0xd000 },
+		{ 0x06, 0xd180 },
+		{ 0x06, 0x1f66 },
+		{ 0x06, 0xe2f8 },
+		{ 0x06, 0xeae3 },
+		{ 0x06, 0xf8eb },
+		{ 0x06, 0x5af8 },
+		{ 0x06, 0x1e20 },
+		{ 0x06, 0xe6f8 },
+		{ 0x06, 0xeae5 },
+		{ 0x06, 0xf8eb },
+		{ 0x06, 0xd302 },
+		{ 0x06, 0xb3fe },
+		{ 0x06, 0xe2f8 },
+		{ 0x06, 0x7cef },
+		{ 0x06, 0x325b },
+		{ 0x06, 0x80e3 },
+		{ 0x06, 0xf87d },
+		{ 0x06, 0x9e03 },
+		{ 0x06, 0x7dff },
+		{ 0x06, 0xff0d },
+		{ 0x06, 0x581c },
+		{ 0x06, 0x551a },
+		{ 0x06, 0x6511 },
+		{ 0x06, 0xa190 },
+		{ 0x06, 0xd3e2 },
+		{ 0x06, 0x8348 },
+		{ 0x06, 0xe383 },
+		{ 0x06, 0x491b },
+		{ 0x06, 0x56ab },
+		{ 0x06, 0x08ef },
+		{ 0x06, 0x56e6 },
+		{ 0x06, 0x8348 },
+		{ 0x06, 0xe783 },
+		{ 0x06, 0x4910 },
+		{ 0x06, 0xd180 },
+		{ 0x06, 0x1f66 },
+		{ 0x06, 0xa004 },
+		{ 0x06, 0xb9e2 },
+		{ 0x06, 0x8348 },
+		{ 0x06, 0xe383 },
+		{ 0x06, 0x49ef },
+		{ 0x06, 0x65e2 },
+		{ 0x06, 0x834a },
+		{ 0x06, 0xe383 },
+		{ 0x06, 0x4b1b },
+		{ 0x06, 0x56aa },
+		{ 0x06, 0x0eef },
+		{ 0x06, 0x56e6 },
+		{ 0x06, 0x834a },
+		{ 0x06, 0xe783 },
+		{ 0x06, 0x4be2 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0xe683 },
+		{ 0x06, 0x4ce0 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0xa000 },
+		{ 0x06, 0x0caf },
+		{ 0x06, 0x81dc },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4d10 },
+		{ 0x06, 0xe483 },
+		{ 0x06, 0x4dae },
+		{ 0x06, 0x0480 },
+		{ 0x06, 0xe483 },
+		{ 0x06, 0x4de0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7803 },
+		{ 0x06, 0x9e0b },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x049e },
+		{ 0x06, 0x04ee },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x02e0 },
+		{ 0x06, 0x8332 },
+		{ 0x06, 0xe183 },
+		{ 0x06, 0x3359 },
+		{ 0x06, 0x0fe2 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0x0c24 },
+		{ 0x06, 0x5af0 },
+		{ 0x06, 0x1e12 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x8ce5 },
+		{ 0x06, 0xf88d },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x30e1 },
+		{ 0x06, 0x8331 },
+		{ 0x06, 0x6801 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x8ae5 },
+		{ 0x06, 0xf88b },
+		{ 0x06, 0xae37 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4e03 },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4ce1 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0x1b01 },
+		{ 0x06, 0x9e04 },
+		{ 0x06, 0xaaa1 },
+		{ 0x06, 0xaea8 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4e04 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4f00 },
+		{ 0x06, 0xaeab },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4f78 },
+		{ 0x06, 0x039f },
+		{ 0x06, 0x14ee },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x05d2 },
+		{ 0x06, 0x40d6 },
+		{ 0x06, 0x5554 },
+		{ 0x06, 0x0282 },
+		{ 0x06, 0x17d2 },
+		{ 0x06, 0xa0d6 },
+		{ 0x06, 0xba00 },
+		{ 0x06, 0x0282 },
+		{ 0x06, 0x17fe },
+		{ 0x06, 0xfdfc },
+		{ 0x06, 0x05f8 },
+		{ 0x06, 0xe0f8 },
+		{ 0x06, 0x60e1 },
+		{ 0x06, 0xf861 },
+		{ 0x06, 0x6802 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x60e5 },
+		{ 0x06, 0xf861 },
+		{ 0x06, 0xe0f8 },
+		{ 0x06, 0x48e1 },
+		{ 0x06, 0xf849 },
+		{ 0x06, 0x580f },
+		{ 0x06, 0x1e02 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x48e5 },
+		{ 0x06, 0xf849 },
+		{ 0x06, 0xd000 },
+		{ 0x06, 0x0282 },
+		{ 0x06, 0x5bbf },
+		{ 0x06, 0x8350 },
+		{ 0x06, 0xef46 },
+		{ 0x06, 0xdc19 },
+		{ 0x06, 0xddd0 },
+		{ 0x06, 0x0102 },
+		{ 0x06, 0x825b },
+		{ 0x06, 0x0282 },
+		{ 0x06, 0x77e0 },
+		{ 0x06, 0xf860 },
+		{ 0x06, 0xe1f8 },
+		{ 0x06, 0x6158 },
+		{ 0x06, 0xfde4 },
+		{ 0x06, 0xf860 },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x61fc },
+		{ 0x06, 0x04f9 },
+		{ 0x06, 0xfafb },
+		{ 0x06, 0xc6bf },
+		{ 0x06, 0xf840 },
+		{ 0x06, 0xbe83 },
+		{ 0x06, 0x50a0 },
+		{ 0x06, 0x0101 },
+		{ 0x06, 0x071b },
+		{ 0x06, 0x89cf },
+		{ 0x06, 0xd208 },
+		{ 0x06, 0xebdb },
+		{ 0x06, 0x19b2 },
+		{ 0x06, 0xfbff },
+		{ 0x06, 0xfefd },
+		{ 0x06, 0x04f8 },
+		{ 0x06, 0xe0f8 },
+		{ 0x06, 0x48e1 },
+		{ 0x06, 0xf849 },
+		{ 0x06, 0x6808 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x48e5 },
+		{ 0x06, 0xf849 },
+		{ 0x06, 0x58f7 },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x48e5 },
+		{ 0x06, 0xf849 },
+		{ 0x06, 0xfc04 },
+		{ 0x06, 0x4d20 },
+		{ 0x06, 0x0002 },
+		{ 0x06, 0x4e22 },
+		{ 0x06, 0x0002 },
+		{ 0x06, 0x4ddf },
+		{ 0x06, 0xff01 },
+		{ 0x06, 0x4edd },
+		{ 0x06, 0xff01 },
+		{ 0x05, 0x83d4 },
+		{ 0x06, 0x8000 },
+		{ 0x05, 0x83d8 },
+		{ 0x06, 0x8051 },
+		{ 0x02, 0x6010 },
+		{ 0x03, 0xdc00 },
+		{ 0x05, 0xfff6 },
+		{ 0x06, 0x00fc },
 		{ 0x1f, 0x0000 },
-		{ 0x14, 0x0060 },
+
 		{ 0x1f, 0x0000 },
-		{ 0x0d, 0xf8a0 },
+		{ 0x0d, 0xf880 },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+	mdio_write(ioaddr, 0x1f, 0x0002);
+	mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef);
+	mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00);
+
+	rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
+
+	if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+		struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x669a },
+			{ 0x1f, 0x0005 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x669a },
+			{ 0x1f, 0x0002 }
+		};
+		int val;
+
+		rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+		val = mdio_read(ioaddr, 0x0d);
+
+		if ((val & 0x00ff) != 0x006c) {
+			u32 set[] = {
+				0x0065, 0x0066, 0x0067, 0x0068,
+				0x0069, 0x006a, 0x006b, 0x006c
+			};
+			int i;
+
+			mdio_write(ioaddr, 0x1f, 0x0002);
+
+			val &= 0xff00;
+			for (i = 0; i < ARRAY_SIZE(set); i++)
+				mdio_write(ioaddr, 0x0d, val | set[i]);
+		}
+	} else {
+		struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x6662 },
+			{ 0x1f, 0x0005 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x6662 }
+		};
+
+		rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+	}
+
+	mdio_write(ioaddr, 0x1f, 0x0002);
+	mdio_patch(ioaddr, 0x0d, 0x0300);
+	mdio_patch(ioaddr, 0x0f, 0x0010);
+
+	mdio_write(ioaddr, 0x1f, 0x0002);
+	mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
+	mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
+
+	rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2));
+}
+
+static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
+{
+	struct phy_reg phy_reg_init_0[] = {
+		{ 0x1f, 0x0001 },
+		{ 0x06, 0x4064 },
+		{ 0x07, 0x2863 },
+		{ 0x08, 0x059c },
+		{ 0x09, 0x26b4 },
+		{ 0x0a, 0x6a19 },
+		{ 0x0b, 0xdcc8 },
+		{ 0x10, 0xf06d },
+		{ 0x14, 0x7f68 },
+		{ 0x18, 0x7fd9 },
+		{ 0x1c, 0xf0ff },
+		{ 0x1d, 0x3d9c },
+		{ 0x1f, 0x0003 },
+		{ 0x12, 0xf49f },
+		{ 0x13, 0x070b },
+		{ 0x1a, 0x05ad },
+		{ 0x14, 0x94c0 },
+
+		{ 0x1f, 0x0002 },
+		{ 0x06, 0x5561 },
 		{ 0x1f, 0x0005 },
-		{ 0x05, 0xffc2 }
+		{ 0x05, 0x8332 },
+		{ 0x06, 0x5561 }
+	};
+	struct phy_reg phy_reg_init_1[] = {
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0xffc2 },
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8000 },
+		{ 0x06, 0xf8f9 },
+		{ 0x06, 0xfaee },
+		{ 0x06, 0xf8ea },
+		{ 0x06, 0x00ee },
+		{ 0x06, 0xf8eb },
+		{ 0x06, 0x00e2 },
+		{ 0x06, 0xf87c },
+		{ 0x06, 0xe3f8 },
+		{ 0x06, 0x7da5 },
+		{ 0x06, 0x1111 },
+		{ 0x06, 0x12d2 },
+		{ 0x06, 0x40d6 },
+		{ 0x06, 0x4444 },
+		{ 0x06, 0x0281 },
+		{ 0x06, 0xc6d2 },
+		{ 0x06, 0xa0d6 },
+		{ 0x06, 0xaaaa },
+		{ 0x06, 0x0281 },
+		{ 0x06, 0xc6ae },
+		{ 0x06, 0x0fa5 },
+		{ 0x06, 0x4444 },
+		{ 0x06, 0x02ae },
+		{ 0x06, 0x4da5 },
+		{ 0x06, 0xaaaa },
+		{ 0x06, 0x02ae },
+		{ 0x06, 0x47af },
+		{ 0x06, 0x81c2 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4e00 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4d0f },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4c0f },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4f00 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x5100 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4aff },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4bff },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x30e1 },
+		{ 0x06, 0x8331 },
+		{ 0x06, 0x58fe },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x8ae5 },
+		{ 0x06, 0xf88b },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x32e1 },
+		{ 0x06, 0x8333 },
+		{ 0x06, 0x590f },
+		{ 0x06, 0xe283 },
+		{ 0x06, 0x4d0c },
+		{ 0x06, 0x245a },
+		{ 0x06, 0xf01e },
+		{ 0x06, 0x12e4 },
+		{ 0x06, 0xf88c },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x8daf },
+		{ 0x06, 0x81c2 },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4f10 },
+		{ 0x06, 0xe483 },
+		{ 0x06, 0x4fe0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7800 },
+		{ 0x06, 0x9f0a },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4fa0 },
+		{ 0x06, 0x10a5 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4e01 },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x059e },
+		{ 0x06, 0x9ae0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7804 },
+		{ 0x06, 0x9e10 },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x039e },
+		{ 0x06, 0x0fe0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7801 },
+		{ 0x06, 0x9e05 },
+		{ 0x06, 0xae0c },
+		{ 0x06, 0xaf81 },
+		{ 0x06, 0xa7af },
+		{ 0x06, 0x8152 },
+		{ 0x06, 0xaf81 },
+		{ 0x06, 0x8baf },
+		{ 0x06, 0x81c2 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4800 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4900 },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x5110 },
+		{ 0x06, 0xe483 },
+		{ 0x06, 0x5158 },
+		{ 0x06, 0x019f },
+		{ 0x06, 0xead0 },
+		{ 0x06, 0x00d1 },
+		{ 0x06, 0x801f },
+		{ 0x06, 0x66e2 },
+		{ 0x06, 0xf8ea },
+		{ 0x06, 0xe3f8 },
+		{ 0x06, 0xeb5a },
+		{ 0x06, 0xf81e },
+		{ 0x06, 0x20e6 },
+		{ 0x06, 0xf8ea },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0xebd3 },
+		{ 0x06, 0x02b3 },
+		{ 0x06, 0xfee2 },
+		{ 0x06, 0xf87c },
+		{ 0x06, 0xef32 },
+		{ 0x06, 0x5b80 },
+		{ 0x06, 0xe3f8 },
+		{ 0x06, 0x7d9e },
+		{ 0x06, 0x037d },
+		{ 0x06, 0xffff },
+		{ 0x06, 0x0d58 },
+		{ 0x06, 0x1c55 },
+		{ 0x06, 0x1a65 },
+		{ 0x06, 0x11a1 },
+		{ 0x06, 0x90d3 },
+		{ 0x06, 0xe283 },
+		{ 0x06, 0x48e3 },
+		{ 0x06, 0x8349 },
+		{ 0x06, 0x1b56 },
+		{ 0x06, 0xab08 },
+		{ 0x06, 0xef56 },
+		{ 0x06, 0xe683 },
+		{ 0x06, 0x48e7 },
+		{ 0x06, 0x8349 },
+		{ 0x06, 0x10d1 },
+		{ 0x06, 0x801f },
+		{ 0x06, 0x66a0 },
+		{ 0x06, 0x04b9 },
+		{ 0x06, 0xe283 },
+		{ 0x06, 0x48e3 },
+		{ 0x06, 0x8349 },
+		{ 0x06, 0xef65 },
+		{ 0x06, 0xe283 },
+		{ 0x06, 0x4ae3 },
+		{ 0x06, 0x834b },
+		{ 0x06, 0x1b56 },
+		{ 0x06, 0xaa0e },
+		{ 0x06, 0xef56 },
+		{ 0x06, 0xe683 },
+		{ 0x06, 0x4ae7 },
+		{ 0x06, 0x834b },
+		{ 0x06, 0xe283 },
+		{ 0x06, 0x4de6 },
+		{ 0x06, 0x834c },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4da0 },
+		{ 0x06, 0x000c },
+		{ 0x06, 0xaf81 },
+		{ 0x06, 0x8be0 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0x10e4 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0xae04 },
+		{ 0x06, 0x80e4 },
+		{ 0x06, 0x834d },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x4e78 },
+		{ 0x06, 0x039e },
+		{ 0x06, 0x0be0 },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x7804 },
+		{ 0x06, 0x9e04 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4e02 },
+		{ 0x06, 0xe083 },
+		{ 0x06, 0x32e1 },
+		{ 0x06, 0x8333 },
+		{ 0x06, 0x590f },
+		{ 0x06, 0xe283 },
+		{ 0x06, 0x4d0c },
+		{ 0x06, 0x245a },
+		{ 0x06, 0xf01e },
+		{ 0x06, 0x12e4 },
+		{ 0x06, 0xf88c },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x8de0 },
+		{ 0x06, 0x8330 },
+		{ 0x06, 0xe183 },
+		{ 0x06, 0x3168 },
+		{ 0x06, 0x01e4 },
+		{ 0x06, 0xf88a },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x8bae },
+		{ 0x06, 0x37ee },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x03e0 },
+		{ 0x06, 0x834c },
+		{ 0x06, 0xe183 },
+		{ 0x06, 0x4d1b },
+		{ 0x06, 0x019e },
+		{ 0x06, 0x04aa },
+		{ 0x06, 0xa1ae },
+		{ 0x06, 0xa8ee },
+		{ 0x06, 0x834e },
+		{ 0x06, 0x04ee },
+		{ 0x06, 0x834f },
+		{ 0x06, 0x00ae },
+		{ 0x06, 0xabe0 },
+		{ 0x06, 0x834f },
+		{ 0x06, 0x7803 },
+		{ 0x06, 0x9f14 },
+		{ 0x06, 0xee83 },
+		{ 0x06, 0x4e05 },
+		{ 0x06, 0xd240 },
+		{ 0x06, 0xd655 },
+		{ 0x06, 0x5402 },
+		{ 0x06, 0x81c6 },
+		{ 0x06, 0xd2a0 },
+		{ 0x06, 0xd6ba },
+		{ 0x06, 0x0002 },
+		{ 0x06, 0x81c6 },
+		{ 0x06, 0xfefd },
+		{ 0x06, 0xfc05 },
+		{ 0x06, 0xf8e0 },
+		{ 0x06, 0xf860 },
+		{ 0x06, 0xe1f8 },
+		{ 0x06, 0x6168 },
+		{ 0x06, 0x02e4 },
+		{ 0x06, 0xf860 },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x61e0 },
+		{ 0x06, 0xf848 },
+		{ 0x06, 0xe1f8 },
+		{ 0x06, 0x4958 },
+		{ 0x06, 0x0f1e },
+		{ 0x06, 0x02e4 },
+		{ 0x06, 0xf848 },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x49d0 },
+		{ 0x06, 0x0002 },
+		{ 0x06, 0x820a },
+		{ 0x06, 0xbf83 },
+		{ 0x06, 0x50ef },
+		{ 0x06, 0x46dc },
+		{ 0x06, 0x19dd },
+		{ 0x06, 0xd001 },
+		{ 0x06, 0x0282 },
+		{ 0x06, 0x0a02 },
+		{ 0x06, 0x8226 },
+		{ 0x06, 0xe0f8 },
+		{ 0x06, 0x60e1 },
+		{ 0x06, 0xf861 },
+		{ 0x06, 0x58fd },
+		{ 0x06, 0xe4f8 },
+		{ 0x06, 0x60e5 },
+		{ 0x06, 0xf861 },
+		{ 0x06, 0xfc04 },
+		{ 0x06, 0xf9fa },
+		{ 0x06, 0xfbc6 },
+		{ 0x06, 0xbff8 },
+		{ 0x06, 0x40be },
+		{ 0x06, 0x8350 },
+		{ 0x06, 0xa001 },
+		{ 0x06, 0x0107 },
+		{ 0x06, 0x1b89 },
+		{ 0x06, 0xcfd2 },
+		{ 0x06, 0x08eb },
+		{ 0x06, 0xdb19 },
+		{ 0x06, 0xb2fb },
+		{ 0x06, 0xfffe },
+		{ 0x06, 0xfd04 },
+		{ 0x06, 0xf8e0 },
+		{ 0x06, 0xf848 },
+		{ 0x06, 0xe1f8 },
+		{ 0x06, 0x4968 },
+		{ 0x06, 0x08e4 },
+		{ 0x06, 0xf848 },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x4958 },
+		{ 0x06, 0xf7e4 },
+		{ 0x06, 0xf848 },
+		{ 0x06, 0xe5f8 },
+		{ 0x06, 0x49fc },
+		{ 0x06, 0x044d },
+		{ 0x06, 0x2000 },
+		{ 0x06, 0x024e },
+		{ 0x06, 0x2200 },
+		{ 0x06, 0x024d },
+		{ 0x06, 0xdfff },
+		{ 0x06, 0x014e },
+		{ 0x06, 0xddff },
+		{ 0x06, 0x0100 },
+		{ 0x05, 0x83d8 },
+		{ 0x06, 0x8000 },
+		{ 0x03, 0xdc00 },
+		{ 0x05, 0xfff6 },
+		{ 0x06, 0x00fc },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0000 },
+		{ 0x0d, 0xf880 },
+		{ 0x1f, 0x0000 }
 	};
 
 	rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
-	if (mdio_read(ioaddr, 0x06) == 0xc400) {
-		struct phy_reg phy_reg_init_1[] = {
+	if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+		struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x669a },
 			{ 0x1f, 0x0005 },
-			{ 0x01, 0x0300 },
-			{ 0x1f, 0x0000 },
-			{ 0x11, 0x401c },
-			{ 0x16, 0x4100 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x669a },
+
+			{ 0x1f, 0x0002 }
+		};
+		int val;
+
+		rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+		val = mdio_read(ioaddr, 0x0d);
+		if ((val & 0x00ff) != 0x006c) {
+			u32 set[] = {
+				0x0065, 0x0066, 0x0067, 0x0068,
+				0x0069, 0x006a, 0x006b, 0x006c
+			};
+			int i;
+
+			mdio_write(ioaddr, 0x1f, 0x0002);
+
+			val &= 0xff00;
+			for (i = 0; i < ARRAY_SIZE(set); i++)
+				mdio_write(ioaddr, 0x0d, val | set[i]);
+		}
+	} else {
+		struct phy_reg phy_reg_init[] = {
+			{ 0x1f, 0x0002 },
+			{ 0x05, 0x2642 },
 			{ 0x1f, 0x0005 },
-			{ 0x07, 0x0010 },
-			{ 0x05, 0x83dc },
-			{ 0x06, 0x087d },
-			{ 0x05, 0x8300 },
-			{ 0x06, 0x0101 },
-			{ 0x06, 0x05f8 },
-			{ 0x06, 0xf9fa },
-			{ 0x06, 0xfbef },
-			{ 0x06, 0x79e2 },
-			{ 0x06, 0x835f },
-			{ 0x06, 0xe0f8 },
-			{ 0x06, 0x9ae1 },
-			{ 0x06, 0xf89b },
-			{ 0x06, 0xef31 },
-			{ 0x06, 0x3b65 },
-			{ 0x06, 0xaa07 },
-			{ 0x06, 0x81e4 },
-			{ 0x06, 0xf89a },
-			{ 0x06, 0xe5f8 },
-			{ 0x06, 0x9baf },
-			{ 0x06, 0x06ae },
-			{ 0x05, 0x83dc },
-			{ 0x06, 0x8300 },
+			{ 0x05, 0x8330 },
+			{ 0x06, 0x2642 }
 		};
 
-		rtl_phy_write(ioaddr, phy_reg_init_1,
-			      ARRAY_SIZE(phy_reg_init_1));
+		rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 	}
 
-	mdio_write(ioaddr, 0x1f, 0x0000);
+	mdio_write(ioaddr, 0x1f, 0x0002);
+	mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
+	mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
+
+	mdio_write(ioaddr, 0x1f, 0x0001);
+	mdio_write(ioaddr, 0x17, 0x0cc0);
+
+	mdio_write(ioaddr, 0x1f, 0x0002);
+	mdio_patch(ioaddr, 0x0f, 0x0017);
+
+	rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
+}
+
+static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr)
+{
+	struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0002 },
+		{ 0x10, 0x0008 },
+		{ 0x0d, 0x006c },
+
+		{ 0x1f, 0x0000 },
+		{ 0x0d, 0xf880 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x0b, 0xa4d8 },
+		{ 0x09, 0x281c },
+		{ 0x07, 0x2883 },
+		{ 0x0a, 0x6b35 },
+		{ 0x1d, 0x3da4 },
+		{ 0x1c, 0xeffd },
+		{ 0x14, 0x7f52 },
+		{ 0x18, 0x7fc6 },
+		{ 0x08, 0x0601 },
+		{ 0x06, 0x4063 },
+		{ 0x10, 0xf074 },
+		{ 0x1f, 0x0003 },
+		{ 0x13, 0x0789 },
+		{ 0x12, 0xf4bd },
+		{ 0x1a, 0x04fd },
+		{ 0x14, 0x84b0 },
+		{ 0x1f, 0x0000 },
+		{ 0x00, 0x9200 },
+
+		{ 0x1f, 0x0005 },
+		{ 0x01, 0x0340 },
+		{ 0x1f, 0x0001 },
+		{ 0x04, 0x4000 },
+		{ 0x03, 0x1d21 },
+		{ 0x02, 0x0c32 },
+		{ 0x01, 0x0200 },
+		{ 0x00, 0x5554 },
+		{ 0x04, 0x4800 },
+		{ 0x04, 0x4000 },
+		{ 0x04, 0xf000 },
+		{ 0x03, 0xdf01 },
+		{ 0x02, 0xdf20 },
+		{ 0x01, 0x101a },
+		{ 0x00, 0xa0ff },
+		{ 0x04, 0xf800 },
+		{ 0x04, 0xf000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0007 },
+		{ 0x1e, 0x0023 },
+		{ 0x16, 0x0000 },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
 static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
@@ -1792,7 +2661,13 @@ static void rtl_hw_phy_config(struct net_device *dev)
 		rtl8168cp_2_hw_phy_config(ioaddr);
 		break;
 	case RTL_GIGA_MAC_VER_25:
-		rtl8168d_hw_phy_config(ioaddr);
+		rtl8168d_1_hw_phy_config(ioaddr);
+		break;
+	case RTL_GIGA_MAC_VER_26:
+		rtl8168d_2_hw_phy_config(ioaddr);
+		break;
+	case RTL_GIGA_MAC_VER_27:
+		rtl8168d_3_hw_phy_config(ioaddr);
 		break;
 
 	default:
@@ -2200,6 +3075,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
 	if (!tp->pcie_cap && netif_msg_probe(tp))
 		dev_info(&pdev->dev, "no PCI Express capability\n");
+	else {
+		pci_write_config_word(pdev, tp->pcie_cap + PCI_EXP_DEVSTA,
+				      PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED |
+				      PCI_EXP_DEVSTA_FED | PCI_EXP_DEVSTA_URD);
+	}
 
 	RTL_W16(IntrMask, 0x0000);
 
@@ -2863,6 +3743,8 @@ static void rtl_hw_start_8168(struct net_device *dev)
 	break;
 
 	case RTL_GIGA_MAC_VER_25:
+	case RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_27:
 		rtl_hw_start_8168d(ioaddr, pdev);
 	break;
 
-- 
Ueimor

^ permalink raw reply related

* Re: N_PPP_SYNC ldisc BUG: sleeping function called from invalid context
From: Tilman Schmidt @ 2009-09-30 22:00 UTC (permalink / raw)
  To: Jarek Poplawski; +Cc: Alan Cox, linux-kernel, netdev, Alan Cox
In-Reply-To: <4AC3BF62.9020706@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 557 bytes --]

Jarek Poplawski schrieb:
> Tilman Schmidt wrote, On 09/30/2009 08:55 PM:
> ...
>> Why then does mutex_lock() complain?
> 
> 
> Maybe it doesn't matter here, but this: 
> 
>> INFO: lockdep is turned off.
> suggests there was some lockdep issue/warning earlier.

That's just because some <deleted> decided that tainted kernels don't deserve lockdep.

-- 
Tilman Schmidt                    E-Mail: tilman@imap.cc
Bonn, Germany
Diese Nachricht besteht zu 100% aus wiederverwerteten Bits.
Ungeöffnet mindestens haltbar bis: (siehe Rückseite)


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

^ permalink raw reply

* [PATCH 2.6.32-rc1] net: VMware virtual Ethernet NIC driver: vmxnet3
From: Shreyas Bhatewara @ 2009-09-30 21:34 UTC (permalink / raw)
  To: linux-kernel, netdev, Stephen Hemminger, David S. Miller, Jeff 
  Cc: Anthony Liguori, Chris Wright, Greg Kroah-Hartman, Andrew Morton,
	virtualization, pv-drivers


Ethernet NIC driver for VMware's vmxnet3

From: Shreyas Bhatewara <sbhatewara@vmware.com>

This patch adds driver support for VMware's virtual Ethernet NIC: vmxnet3
Guests running on VMware hypervisors supporting vmxnet3 device will thus have 
access to improved network functionalities and performance.

Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>

---

VMware virtual Ethernet NIC Driver : vmxnet3 - v2

Changelog (v2-v1)
- Rebased the patch to v2.6.32-rc1
- Changed all uint32_t types to u32 and friends
- Removed duplicate max queue size from upt1_defs.h
- Replaced #defines by enum
- uniform spacing between datatype and membername in structures
- removed some noisy printks, eliminated some BUG_ONs
- corrected arguments of kcalloc
- used pc_request_selected_regions, pci_enable_dev_mem
- elminated not-so-useful wrapper functions, used eth_op_ functions instead
- used strlcpy
- used get_sset_counts instead of get_stats_count
- used net_device_stats from struct net_device


Please review the patch and provide your feedback.

Thanking you
->Shreyas

---

diff --git a/MAINTAINERS b/MAINTAINERS
index c450f3a..f65398a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5608,6 +5608,13 @@ S:	Maintained
  F:	drivers/vlynq/vlynq.c
  F:	include/linux/vlynq.h

+VMWARE VMXNET3 ETHERNET DRIVER
+M:     Shreyas Bhatewara <sbhatewara@vmware.com>
+M:     VMware PV-Drivers <pv-drivers@vmware.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/vmxnet3/
+
  VOLTAGE AND CURRENT REGULATOR FRAMEWORK
  M:	Liam Girdwood <lrg@slimlogic.co.uk>
  M:	Mark Brown <broonie@opensource.wolfsonmicro.com>
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2bea67c..3b131d2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3223,4 +3223,12 @@ config VIRTIO_NET
  	  This is the virtual network driver for virtio.  It can be used with
            lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.

+config VMXNET3
+       tristate "VMware VMXNET3 ethernet driver"
+       depends on PCI && X86
+       help
+         This driver supports VMware's vmxnet3 virtual ethernet NIC.
+         To compile this driver as a module, choose M here: the
+         module will be called vmxnet3.
+
  endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index ae8cd30..49d28a3 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_TEHUTI) += tehuti.o
  obj-$(CONFIG_ENIC) += enic/
  obj-$(CONFIG_JME) += jme.o
  obj-$(CONFIG_BE2NET) += benet/
+obj-$(CONFIG_VMXNET3) += vmxnet3/

  gianfar_driver-objs := gianfar.o \
  		gianfar_ethtool.o \
diff --git a/drivers/net/vmxnet3/Makefile b/drivers/net/vmxnet3/Makefile
new file mode 100644
index 0000000..880f509
--- /dev/null
+++ b/drivers/net/vmxnet3/Makefile
@@ -0,0 +1,35 @@
+################################################################################
+#
+# Linux driver for VMware's vmxnet3 ethernet NIC.
+#
+# Copyright (C) 2007-2009, VMware, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License and no later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+# NON INFRINGEMENT.  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".
+#
+# Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+#
+#
+################################################################################
+
+#
+# Makefile for the VMware vmxnet3 ethernet NIC driver
+#
+
+obj-$(CONFIG_VMXNET3) += vmxnet3.o
+
+vmxnet3-objs := vmxnet3_drv.o vmxnet3_ethtool.o
diff --git a/drivers/net/vmxnet3/upt1_defs.h b/drivers/net/vmxnet3/upt1_defs.h
new file mode 100644
index 0000000..6a49d04
--- /dev/null
+++ b/drivers/net/vmxnet3/upt1_defs.h
@@ -0,0 +1,99 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  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".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ * Definitions for Uniform Pass Through, a framework developed by VMware
+ * along with it's IHV partners to implement the fast path features of
+ * vmxnet3 in silicon.
+ */
+
+#ifndef _UPT1_DEFS_H
+#define _UPT1_DEFS_H
+
+struct UPT1_TxStats {
+	u64			TSOPktsTxOK;  /* TSO pkts post-segmentation */
+	u64			TSOBytesTxOK;
+	u64			ucastPktsTxOK;
+	u64			ucastBytesTxOK;
+	u64			mcastPktsTxOK;
+	u64			mcastBytesTxOK;
+	u64			bcastPktsTxOK;
+	u64			bcastBytesTxOK;
+	u64			pktsTxError;
+	u64			pktsTxDiscard;
+};
+
+struct UPT1_RxStats {
+	u64			LROPktsRxOK;    /* LRO pkts */
+	u64			LROBytesRxOK;   /* bytes from LRO pkts */
+	/* the following counters are for pkts from the wire, i.e., pre-LRO */
+	u64			ucastPktsRxOK;
+	u64			ucastBytesRxOK;
+	u64			mcastPktsRxOK;
+	u64			mcastBytesRxOK;
+	u64			bcastPktsRxOK;
+	u64			bcastBytesRxOK;
+	u64			pktsRxOutOfBuf;
+	u64			pktsRxError;
+};
+
+/* interrupt moderation level */
+enum {
+	UPT1_IML_NONE		= 0, /* no interrupt moderation */
+	UPT1_IML_HIGHEST	= 7, /* least intr generated */
+	UPT1_IML_ADAPTIVE	= 8, /* adpative intr moderation */
+};
+/* values for UPT1_RSSConf.hashFunc */
+enum {
+	UPT1_RSS_HASH_TYPE_NONE      = 0x0,
+	UPT1_RSS_HASH_TYPE_IPV4      = 0x01,
+	UPT1_RSS_HASH_TYPE_TCP_IPV4  = 0x02,
+	UPT1_RSS_HASH_TYPE_IPV6      = 0x04,
+	UPT1_RSS_HASH_TYPE_TCP_IPV6  = 0x08,
+};
+
+enum {
+	UPT1_RSS_HASH_FUNC_NONE      = 0x0,
+	UPT1_RSS_HASH_FUNC_TOEPLITZ  = 0x01,
+};
+
+#define UPT1_RSS_MAX_KEY_SIZE        40
+#define UPT1_RSS_MAX_IND_TABLE_SIZE  128
+
+struct UPT1_RSSConf {
+	u16			hashType;
+	u16			hashFunc;
+	u16			hashKeySize;
+	u16			indTableSize;
+	u8			hashKey[UPT1_RSS_MAX_KEY_SIZE];
+	u8			indTable[UPT1_RSS_MAX_IND_TABLE_SIZE];
+};
+
+/* features */
+enum {
+	UPT1_F_RXCSUM		= 0x0001,   /* rx csum verification */
+	UPT1_F_RSS		= 0x0002,
+	UPT1_F_RXVLAN		= 0x0004,   /* VLAN tag stripping */
+	UPT1_F_LRO		= 0x0008,
+};
+#endif
diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h 
b/drivers/net/vmxnet3/vmxnet3_defs.h
new file mode 100644
index 0000000..dc8ee44
--- /dev/null
+++ b/drivers/net/vmxnet3/vmxnet3_defs.h
@@ -0,0 +1,535 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  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".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#ifndef _VMXNET3_DEFS_H_
+#define _VMXNET3_DEFS_H_
+
+#include "upt1_defs.h"
+
+/* all registers are 32 bit wide */
+/* BAR 1 */
+enum {
+	VMXNET3_REG_VRRS	= 0x0,	/* Vmxnet3 Revision Report Selection */
+	VMXNET3_REG_UVRS	= 0x8,	/* UPT Version Report Selection */
+	VMXNET3_REG_DSAL	= 0x10,	/* Driver Shared Address Low */
+	VMXNET3_REG_DSAH	= 0x18,	/* Driver Shared Address High */
+	VMXNET3_REG_CMD		= 0x20,	/* Command */
+	VMXNET3_REG_MACL	= 0x28,	/* MAC Address Low */
+	VMXNET3_REG_MACH	= 0x30,	/* MAC Address High */
+	VMXNET3_REG_ICR		= 0x38,	/* Interrupt Cause Register */
+	VMXNET3_REG_ECR		= 0x40	/* Event Cause Register */
+};
+
+/* BAR 0 */
+enum {
+	VMXNET3_REG_IMR		= 0x0,	 /* Interrupt Mask Register */
+	VMXNET3_REG_TXPROD	= 0x600, /* Tx Producer Index */
+	VMXNET3_REG_RXPROD	= 0x800, /* Rx Producer Index for ring 1 */
+	VMXNET3_REG_RXPROD2	= 0xA00	 /* Rx Producer Index for ring 2 */
+};
+
+#define VMXNET3_PT_REG_SIZE     4096	/* BAR 0 */
+#define VMXNET3_VD_REG_SIZE     4096	/* BAR 1 */
+
+#define VMXNET3_REG_ALIGN       8	/* All registers are 8-byte aligned. */
+#define VMXNET3_REG_ALIGN_MASK  0x7
+
+/* I/O Mapped access to registers */
+#define VMXNET3_IO_TYPE_PT              0
+#define VMXNET3_IO_TYPE_VD              1
+#define VMXNET3_IO_ADDR(type, reg)      (((type) << 24) | ((reg) & 0xFFFFFF))
+#define VMXNET3_IO_TYPE(addr)           ((addr) >> 24)
+#define VMXNET3_IO_REG(addr)            ((addr) & 0xFFFFFF)
+
+enum {
+	VMXNET3_CMD_FIRST_SET = 0xCAFE0000,
+	VMXNET3_CMD_ACTIVATE_DEV = VMXNET3_CMD_FIRST_SET,
+	VMXNET3_CMD_QUIESCE_DEV,
+	VMXNET3_CMD_RESET_DEV,
+	VMXNET3_CMD_UPDATE_RX_MODE,
+	VMXNET3_CMD_UPDATE_MAC_FILTERS,
+	VMXNET3_CMD_UPDATE_VLAN_FILTERS,
+	VMXNET3_CMD_UPDATE_RSSIDT,
+	VMXNET3_CMD_UPDATE_IML,
+	VMXNET3_CMD_UPDATE_PMCFG,
+	VMXNET3_CMD_UPDATE_FEATURE,
+	VMXNET3_CMD_LOAD_PLUGIN,
+
+	VMXNET3_CMD_FIRST_GET = 0xF00D0000,
+	VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
+	VMXNET3_CMD_GET_STATS,
+	VMXNET3_CMD_GET_LINK,
+	VMXNET3_CMD_GET_PERM_MAC_LO,
+	VMXNET3_CMD_GET_PERM_MAC_HI,
+	VMXNET3_CMD_GET_DID_LO,
+	VMXNET3_CMD_GET_DID_HI,
+	VMXNET3_CMD_GET_DEV_EXTRA_INFO,
+	VMXNET3_CMD_GET_CONF_INTR
+};
+
+struct Vmxnet3_TxDesc {
+	u64		addr;
+
+	u32		len:14;
+	u32		gen:1;      /* generation bit */
+	u32		rsvd:1;
+	u32		dtype:1;    /* descriptor type */
+	u32		ext1:1;
+	u32		msscof:14;  /* MSS, checksum offset, flags */
+
+	u32		hlen:10;    /* header len */
+	u32		om:2;       /* offload mode */
+	u32		eop:1;      /* End Of Packet */
+	u32		cq:1;       /* completion request */
+	u32		ext2:1;
+	u32		ti:1;       /* VLAN Tag Insertion */
+	u32		tci:16;     /* Tag to Insert */
+};
+
+/* TxDesc.OM values */
+#define VMXNET3_OM_NONE		0
+#define VMXNET3_OM_CSUM		2
+#define VMXNET3_OM_TSO		3
+
+/* fields in TxDesc we access w/o using bit fields */
+#define VMXNET3_TXD_EOP_SHIFT	12
+#define VMXNET3_TXD_CQ_SHIFT	13
+#define VMXNET3_TXD_GEN_SHIFT	14
+
+#define VMXNET3_TXD_CQ		(1 << VMXNET3_TXD_CQ_SHIFT)
+#define VMXNET3_TXD_EOP		(1 << VMXNET3_TXD_EOP_SHIFT)
+#define VMXNET3_TXD_GEN		(1 << VMXNET3_TXD_GEN_SHIFT)
+
+#define VMXNET3_HDR_COPY_SIZE   128
+
+
+struct Vmxnet3_TxDataDesc {
+	u8		data[VMXNET3_HDR_COPY_SIZE];
+};
+
+
+struct Vmxnet3_TxCompDesc {
+	u32		txdIdx:12;    /* Index of the EOP TxDesc */
+	u32		ext1:20;
+
+	u32		ext2;
+	u32		ext3;
+
+	u32		rsvd:24;
+	u32		type:7;       /* completion type */
+	u32		gen:1;        /* generation bit */
+};
+
+
+struct Vmxnet3_RxDesc {
+	u64		addr;
+
+	u32		len:14;
+	u32		btype:1;      /* Buffer Type */
+	u32		dtype:1;      /* Descriptor type */
+	u32		rsvd:15;
+	u32		gen:1;        /* Generation bit */
+
+	u32		ext1;
+};
+
+/* values of RXD.BTYPE */
+#define VMXNET3_RXD_BTYPE_HEAD   0    /* head only */
+#define VMXNET3_RXD_BTYPE_BODY   1    /* body only */
+
+/* fields in RxDesc we access w/o using bit fields */
+#define VMXNET3_RXD_BTYPE_SHIFT  14
+#define VMXNET3_RXD_GEN_SHIFT    31
+
+
+struct Vmxnet3_RxCompDesc {
+	u32		rxdIdx:12;    /* Index of the RxDesc */
+	u32		ext1:2;
+	u32		eop:1;        /* End of Packet */
+	u32		sop:1;        /* Start of Packet */
+	u32		rqID:10;      /* rx queue/ring ID */
+	u32		rssType:4;    /* RSS hash type used */
+	u32		cnc:1;        /* Checksum Not Calculated */
+	u32		ext2:1;
+
+	u32		rssHash;      /* RSS hash value */
+
+	u32		len:14;       /* data length */
+	u32		err:1;        /* Error */
+	u32		ts:1;         /* Tag is stripped */
+	u32		tci:16;       /* Tag stripped */
+
+	u32		csum:16;
+	u32		tuc:1;        /* TCP/UDP Checksum Correct */
+	u32		udp:1;        /* UDP packet */
+	u32		tcp:1;        /* TCP packet */
+	u32		ipc:1;        /* IP Checksum Correct */
+	u32		v6:1;         /* IPv6 */
+	u32		v4:1;         /* IPv4 */
+	u32		frg:1;        /* IP Fragment */
+	u32		fcs:1;        /* Frame CRC correct */
+	u32		type:7;       /* completion type */
+	u32		gen:1;        /* generation bit */
+};
+
+/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */
+#define VMXNET3_RCD_TUC_SHIFT	16
+#define VMXNET3_RCD_IPC_SHIFT	19
+
+/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.qword[1] */
+#define VMXNET3_RCD_TYPE_SHIFT	56
+#define VMXNET3_RCD_GEN_SHIFT	63
+
+/* csum OK for TCP/UDP pkts over IP */
+#define VMXNET3_RCD_CSUM_OK (1 << VMXNET3_RCD_TUC_SHIFT | \
+			     1 << VMXNET3_RCD_IPC_SHIFT)
+
+/* value of RxCompDesc.rssType */
+enum {
+	VMXNET3_RCD_RSS_TYPE_NONE     = 0,
+	VMXNET3_RCD_RSS_TYPE_IPV4     = 1,
+	VMXNET3_RCD_RSS_TYPE_TCPIPV4  = 2,
+	VMXNET3_RCD_RSS_TYPE_IPV6     = 3,
+	VMXNET3_RCD_RSS_TYPE_TCPIPV6  = 4,
+};
+
+
+/* a union for accessing all cmd/completion descriptors */
+union Vmxnet3_GenericDesc {
+	u64				qword[2];
+	u32				dword[4];
+	u16				word[8];
+	struct Vmxnet3_TxDesc		txd;
+	struct Vmxnet3_RxDesc		rxd;
+	struct Vmxnet3_TxCompDesc	tcd;
+	struct Vmxnet3_RxCompDesc	rcd;
+};
+
+#define VMXNET3_INIT_GEN       1
+
+/* Max size of a single tx buffer */
+#define VMXNET3_MAX_TX_BUF_SIZE  (1 << 14)
+
+/* # of tx desc needed for a tx buffer size */
+#define VMXNET3_TXD_NEEDED(size) (((size) + VMXNET3_MAX_TX_BUF_SIZE - 1) / \
+				  VMXNET3_MAX_TX_BUF_SIZE)
+
+/* max # of tx descs for a non-tso pkt */
+#define VMXNET3_MAX_TXD_PER_PKT 16
+
+/* Max size of a single rx buffer */
+#define VMXNET3_MAX_RX_BUF_SIZE  ((1 << 14) - 1)
+/* Minimum size of a type 0 buffer */
+#define VMXNET3_MIN_T0_BUF_SIZE  128
+#define VMXNET3_MAX_CSUM_OFFSET  1024
+
+/* Ring base address alignment */
+#define VMXNET3_RING_BA_ALIGN   512
+#define VMXNET3_RING_BA_MASK    (VMXNET3_RING_BA_ALIGN - 1)
+
+/* Ring size must be a multiple of 32 */
+#define VMXNET3_RING_SIZE_ALIGN 32
+#define VMXNET3_RING_SIZE_MASK  (VMXNET3_RING_SIZE_ALIGN - 1)
+
+/* Max ring size */
+#define VMXNET3_TX_RING_MAX_SIZE   4096
+#define VMXNET3_TC_RING_MAX_SIZE   4096
+#define VMXNET3_RX_RING_MAX_SIZE   4096
+#define VMXNET3_RC_RING_MAX_SIZE   8192
+
+/* a list of reasons for queue stop */
+
+enum {
+ VMXNET3_ERR_NOEOP        = 0x80000000,  /* cannot find the EOP desc of a pkt 
*/
+ VMXNET3_ERR_TXD_REUSE    = 0x80000001,  /* reuse TxDesc before tx completion 
*/
+ VMXNET3_ERR_BIG_PKT      = 0x80000002,  /* too many TxDesc for a pkt */
+ VMXNET3_ERR_DESC_NOT_SPT = 0x80000003,  /* descriptor type not supported */
+ VMXNET3_ERR_SMALL_BUF    = 0x80000004,  /* type 0 buffer too small */
+ VMXNET3_ERR_STRESS       = 0x80000005,  /* stress option firing in vmkernel 
*/
+ VMXNET3_ERR_SWITCH       = 0x80000006,  /* mode switch failure */
+ VMXNET3_ERR_TXD_INVALID  = 0x80000007,  /* invalid TxDesc */
+};
+
+/* completion descriptor types */
+#define VMXNET3_CDTYPE_TXCOMP      0    /* Tx Completion Descriptor */
+#define VMXNET3_CDTYPE_RXCOMP      3    /* Rx Completion Descriptor */
+
+enum {
+	VMXNET3_GOS_BITS_UNK    = 0,   /* unknown */
+	VMXNET3_GOS_BITS_32     = 1,
+	VMXNET3_GOS_BITS_64     = 2,
+};
+
+#define VMXNET3_GOS_TYPE_LINUX	1
+
+
+struct Vmxnet3_GOSInfo {
+	u32				gosBits:2;	/* 32-bit or 64-bit? */
+	u32				gosType:4;   /* which guest */
+	u32				gosVer:16;   /* gos version */
+	u32				gosMisc:10;  /* other info about gos */
+};
+
+
+struct Vmxnet3_DriverInfo {
+	u32				version;
+	struct Vmxnet3_GOSInfo		gos;
+	u32				vmxnet3RevSpt;
+	u32				uptVerSpt;
+};
+
+
+#define VMXNET3_REV1_MAGIC  0xbabefee1
+
+/*
+ * QueueDescPA must be 128 bytes aligned. It points to an array of
+ * Vmxnet3_TxQueueDesc followed by an array of Vmxnet3_RxQueueDesc.
+ * The number of Vmxnet3_TxQueueDesc/Vmxnet3_RxQueueDesc are specified by
+ * Vmxnet3_MiscConf.numTxQueues/numRxQueues, respectively.
+ */
+#define VMXNET3_QUEUE_DESC_ALIGN  128
+
+
+struct Vmxnet3_MiscConf {
+	struct Vmxnet3_DriverInfo driverInfo;
+	u64		uptFeatures;
+	u64		ddPA;         /* driver data PA */
+	u64		queueDescPA;  /* queue descriptor table PA */
+	u32		ddLen;        /* driver data len */
+	u32		queueDescLen; /* queue desc. table len in bytes */
+	u32		mtu;
+	u16		maxNumRxSG;
+	u8		numTxQueues;
+	u8		numRxQueues;
+	u32		reserved[4];
+};
+
+
+struct Vmxnet3_TxQueueConf {
+	u64		txRingBasePA;
+	u64		dataRingBasePA;
+	u64		compRingBasePA;
+	u64		ddPA;         /* driver data */
+	u64		reserved;
+	u32		txRingSize;   /* # of tx desc */
+	u32		dataRingSize; /* # of data desc */
+	u32		compRingSize; /* # of comp desc */
+	u32		ddLen;        /* size of driver data */
+	u8		intrIdx;
+	u8		_pad[7];
+};
+
+
+struct Vmxnet3_RxQueueConf {
+	u64		rxRingBasePA[2];
+	u64		compRingBasePA;
+	u64		ddPA;            /* driver data */
+	u64		reserved;
+	u32		rxRingSize[2];   /* # of rx desc */
+	u32		compRingSize;    /* # of rx comp desc */
+	u32		ddLen;           /* size of driver data */
+	u8		intrIdx;
+	u8		_pad[7];
+};
+
+
+enum vmxnet3_intr_mask_mode {
+	VMXNET3_IMM_AUTO   = 0,
+	VMXNET3_IMM_ACTIVE = 1,
+	VMXNET3_IMM_LAZY   = 2
+};
+
+enum vmxnet3_intr_type {
+	VMXNET3_IT_AUTO = 0,
+	VMXNET3_IT_INTX = 1,
+	VMXNET3_IT_MSI  = 2,
+	VMXNET3_IT_MSIX = 3
+};
+
+#define VMXNET3_MAX_TX_QUEUES  8
+#define VMXNET3_MAX_RX_QUEUES  16
+/* addition 1 for events */
+#define VMXNET3_MAX_INTRS      25
+
+
+struct Vmxnet3_IntrConf {
+	bool		autoMask;
+	u8		numIntrs;      /* # of interrupts */
+	u8		eventIntrIdx;
+	u8		modLevels[VMXNET3_MAX_INTRS];	/* moderation level for
+							 * each intr */
+	u32		reserved[3];
+};
+
+/* one bit per VLAN ID, the size is in the units of u32	*/
+#define VMXNET3_VFT_SIZE  (4096 / (sizeof(u32) * 8))
+
+
+struct Vmxnet3_QueueStatus {
+	bool		stopped;
+	u8		_pad[3];
+	u32		error;
+};
+
+
+struct Vmxnet3_TxQueueCtrl {
+	u32		txNumDeferred;
+	u32		txThreshold;
+	u64		reserved;
+};
+
+
+struct Vmxnet3_RxQueueCtrl {
+	bool		updateRxProd;
+	u8		_pad[7];
+	u64		reserved;
+};
+
+enum {
+	VMXNET3_RXM_UCAST     = 0x01,  /* unicast only */
+	VMXNET3_RXM_MCAST     = 0x02,  /* multicast passing the filters */
+	VMXNET3_RXM_BCAST     = 0x04,  /* broadcast only */
+	VMXNET3_RXM_ALL_MULTI = 0x08,  /* all multicast */
+	VMXNET3_RXM_PROMISC   = 0x10  /* promiscuous */
+};
+
+struct Vmxnet3_RxFilterConf {
+	u32		rxMode;       /* VMXNET3_RXM_xxx */
+	u16		mfTableLen;   /* size of the multicast filter table */
+	u16		_pad1;
+	u64		mfTablePA;    /* PA of the multicast filters table */
+	u32		vfTable[VMXNET3_VFT_SIZE]; /* vlan filter */
+};
+
+
+#define VMXNET3_PM_MAX_FILTERS        6
+#define VMXNET3_PM_MAX_PATTERN_SIZE   128
+#define VMXNET3_PM_MAX_MASK_SIZE      (VMXNET3_PM_MAX_PATTERN_SIZE / 8)
+
+#define VMXNET3_PM_WAKEUP_MAGIC       0x01  /* wake up on magic pkts */
+#define VMXNET3_PM_WAKEUP_FILTER      0x02  /* wake up on pkts matching
+					     * filters */
+
+
+struct Vmxnet3_PM_PktFilter {
+	u8		maskSize;
+	u8		patternSize;
+	u8		mask[VMXNET3_PM_MAX_MASK_SIZE];
+	u8		pattern[VMXNET3_PM_MAX_PATTERN_SIZE];
+	u8		pad[6];
+};
+
+
+struct Vmxnet3_PMConf {
+	u16		wakeUpEvents;  /* VMXNET3_PM_WAKEUP_xxx */
+	u8		numFilters;
+	u8		pad[5];
+	struct Vmxnet3_PM_PktFilter filters[VMXNET3_PM_MAX_FILTERS];
+};
+
+
+struct Vmxnet3_VariableLenConfDesc {
+	u32		confVer;
+	u32		confLen;
+	u64		confPA;
+};
+
+
+struct Vmxnet3_TxQueueDesc {
+	struct Vmxnet3_TxQueueCtrl		ctrl;
+	struct Vmxnet3_TxQueueConf		conf;
+
+	/* Driver read after a GET command */
+	struct Vmxnet3_QueueStatus		status;
+	struct UPT1_TxStats			stats;
+	u8					_pad[88]; /* 128 aligned */
+};
+
+
+struct Vmxnet3_RxQueueDesc {
+	struct Vmxnet3_RxQueueCtrl		ctrl;
+	struct Vmxnet3_RxQueueConf		conf;
+	/* Driver read after a GET commad */
+	struct Vmxnet3_QueueStatus		status;
+	struct UPT1_RxStats			stats;
+	u8				      __pad[88]; /* 128 aligned */
+};
+
+
+struct Vmxnet3_DSDevRead {
+	/* read-only region for device, read by dev in response to a SET cmd */
+	struct Vmxnet3_MiscConf			misc;
+	struct Vmxnet3_IntrConf			intrConf;
+	struct Vmxnet3_RxFilterConf		rxFilterConf;
+	struct Vmxnet3_VariableLenConfDesc	rssConfDesc;
+	struct Vmxnet3_VariableLenConfDesc	pmConfDesc;
+	struct Vmxnet3_VariableLenConfDesc	pluginConfDesc;
+};
+
+/* All structures in DriverShared are padded to multiples of 8 bytes */
+struct Vmxnet3_DriverShared {
+	u32				magic;
+	/* make devRead start at 64bit boundaries */
+	u32					pad;
+	struct Vmxnet3_DSDevRead		devRead;
+	u32					ecr;
+	u32					reserved[5];
+};
+
+
+#define VMXNET3_ECR_RQERR       (1 << 0)
+#define VMXNET3_ECR_TQERR       (1 << 1)
+#define VMXNET3_ECR_LINK        (1 << 2)
+#define VMXNET3_ECR_DIC         (1 << 3)
+#define VMXNET3_ECR_DEBUG       (1 << 4)
+
+/* flip the gen bit of a ring */
+#define VMXNET3_FLIP_RING_GEN(gen) ((gen) = (gen) ^ 0x1)
+
+/* only use this if moving the idx won't affect the gen bit */
+#define VMXNET3_INC_RING_IDX_ONLY(idx, ring_size) \
+	do {\
+		(idx)++;\
+		if (unlikely((idx) == (ring_size))) {\
+			(idx) = 0;\
+		} \
+	} while (0)
+
+#define VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid) \
+	(vfTable[vid >> 5] |= (1 << (vid & 31)))
+#define VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid) \
+	(vfTable[vid >> 5] &= ~(1 << (vid & 31)))
+
+#define VMXNET3_VFTABLE_ENTRY_IS_SET(vfTable, vid) \
+	((vfTable[vid >> 5] & (1 << (vid & 31))) != 0)
+
+#define VMXNET3_MAX_MTU     9000
+#define VMXNET3_MIN_MTU     60
+
+#define VMXNET3_LINK_UP         (10000 << 16 | 1)    /* 10 Gbps, up */
+#define VMXNET3_LINK_DOWN       0
+
+#endif /* _VMXNET3_DEFS_H_ */
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c 
b/drivers/net/vmxnet3/vmxnet3_drv.c
new file mode 100644
index 0000000..b47fd41
--- /dev/null
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -0,0 +1,2561 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. 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".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#include "vmxnet3_int.h"
+
+char vmxnet3_driver_name[] = "vmxnet3";
+#define VMXNET3_DRIVER_DESC "VMware vmxnet3 virtual NIC driver"
+
+
+/*
+ * PCI Device ID Table
+ * Last entry must be all 0s
+ */
+static const struct pci_device_id vmxnet3_pciid_table[] = {
+	{PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_VMXNET3)},
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, vmxnet3_pciid_table);
+
+static int disable_lro;
+static atomic_t devices_found;
+
+
+/*
+ *    Enable/Disable the given intr
+ */
+static void
+vmxnet3_enable_intr(struct vmxnet3_adapter *adapter, unsigned intr_idx)
+{
+	VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_IMR + intr_idx * 8, 0);
+}
+
+
+static void
+vmxnet3_disable_intr(struct vmxnet3_adapter *adapter, unsigned intr_idx)
+{
+	VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_IMR + intr_idx * 8, 1);
+}
+
+
+/*
+ *    Enable/Disable all intrs used by the device
+ */
+static void
+vmxnet3_enable_all_intrs(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->intr.num_intrs; i++)
+		vmxnet3_enable_intr(adapter, i);
+}
+
+
+static void
+vmxnet3_disable_all_intrs(struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->intr.num_intrs; i++)
+		vmxnet3_disable_intr(adapter, i);
+}
+
+
+static void
+vmxnet3_ack_events(struct vmxnet3_adapter *adapter, u32 events)
+{
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_ECR, events);
+}
+
+
+static bool
+vmxnet3_tq_stopped(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter 
*adapter)
+{
+	return netif_queue_stopped(adapter->netdev);
+}
+
+
+static void
+vmxnet3_tq_start(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+	tq->stopped = false;
+	netif_start_queue(adapter->netdev);
+}
+
+
+static void
+vmxnet3_tq_wake(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+	tq->stopped = false;
+	netif_wake_queue(adapter->netdev);
+}
+
+
+static void
+vmxnet3_tq_stop(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+	tq->stopped = true;
+	tq->num_stop++;
+	netif_stop_queue(adapter->netdev);
+}
+
+
+/*
+ * Check the link state. This may start or stop the tx queue.
+ */
+static void
+vmxnet3_check_link(struct vmxnet3_adapter *adapter)
+{
+	u32 ret;
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
+	ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+	adapter->link_speed = ret >> 16;
+	if (ret & 1) { /* Link is up. */
+		printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n",
+		       adapter->netdev->name, adapter->link_speed);
+		if (!netif_carrier_ok(adapter->netdev))
+			netif_carrier_on(adapter->netdev);
+
+		vmxnet3_tq_start(&adapter->tx_queue, adapter);
+	} else {
+		printk(KERN_INFO "%s: NIC Link is Down\n",
+		       adapter->netdev->name);
+		if (netif_carrier_ok(adapter->netdev))
+			netif_carrier_off(adapter->netdev);
+
+		vmxnet3_tq_stop(&adapter->tx_queue, adapter);
+	}
+}
+
+
+static void
+vmxnet3_process_events(struct vmxnet3_adapter *adapter)
+{
+	u32 events = adapter->shared->ecr;
+	if (!events)
+		return;
+
+	vmxnet3_ack_events(adapter, events);
+
+	/* Check if link state has changed */
+	if (events & VMXNET3_ECR_LINK)
+		vmxnet3_check_link(adapter);
+
+	/* Check if there is an error on xmit/recv queues */
+	if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
+		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+				       VMXNET3_CMD_GET_QUEUE_STATUS);
+
+		if (adapter->tqd_start->status.stopped) {
+			printk(KERN_ERR "%s: tq error 0x%x\n",
+			       adapter->netdev->name,
+			       adapter->tqd_start->status.error);
+		}
+		if (adapter->rqd_start->status.stopped) {
+			printk(KERN_ERR "%s: rq error 0x%x\n",
+			       adapter->netdev->name,
+			       adapter->rqd_start->status.error);
+		}
+
+		schedule_work(&adapter->work);
+	}
+}
+
+
+static void
+vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi,
+		     struct pci_dev *pdev)
+{
+	if (tbi->map_type == VMXNET3_MAP_SINGLE)
+		pci_unmap_single(pdev, tbi->dma_addr, tbi->len,
+				 PCI_DMA_TODEVICE);
+	else if (tbi->map_type == VMXNET3_MAP_PAGE)
+		pci_unmap_page(pdev, tbi->dma_addr, tbi->len,
+			       PCI_DMA_TODEVICE);
+	else
+		BUG_ON(tbi->map_type != VMXNET3_MAP_NONE);
+
+	tbi->map_type = VMXNET3_MAP_NONE; /* to help debugging */
+}
+
+
+static int
+vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq,
+		  struct pci_dev *pdev,	struct vmxnet3_adapter *adapter)
+{
+	struct sk_buff *skb;
+	int entries = 0;
+
+	/* no out of order completion */
+	BUG_ON(tq->buf_info[eop_idx].sop_idx != tq->tx_ring.next2comp);
+	BUG_ON(tq->tx_ring.base[eop_idx].txd.eop != 1);
+
+	skb = tq->buf_info[eop_idx].skb;
+	BUG_ON(skb == NULL);
+	tq->buf_info[eop_idx].skb = NULL;
+
+	VMXNET3_INC_RING_IDX_ONLY(eop_idx, tq->tx_ring.size);
+
+	while (tq->tx_ring.next2comp != eop_idx) {
+		vmxnet3_unmap_tx_buf(tq->buf_info + tq->tx_ring.next2comp,
+				     pdev);
+
+		/* update next2comp w/o tx_lock. Since we are marking more,
+		 * instead of less, tx ring entries avail, the worst case is
+		 * that the tx routine incorrectly re-queues a pkt due to
+		 * insufficient tx ring entries.
+		 */
+		vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring);
+		entries++;
+	}
+
+	dev_kfree_skb_any(skb);
+	return entries;
+}
+
+
+static int
+vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq,
+			struct vmxnet3_adapter *adapter)
+{
+	int completed = 0;
+	union Vmxnet3_GenericDesc *gdesc;
+
+	gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
+	while (gdesc->tcd.gen == tq->comp_ring.gen) {
+		completed += vmxnet3_unmap_pkt(gdesc->tcd.txdIdx, tq,
+					       adapter->pdev, adapter);
+
+		vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring);
+		gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
+	}
+
+	if (completed) {
+		spin_lock(&tq->tx_lock);
+		if (unlikely(vmxnet3_tq_stopped(tq, adapter) &&
+			     vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) >
+			     VMXNET3_WAKE_QUEUE_THRESHOLD(tq) &&
+			     netif_carrier_ok(adapter->netdev))) {
+			vmxnet3_tq_wake(tq, adapter);
+		}
+		spin_unlock(&tq->tx_lock);
+	}
+	return completed;
+}
+
+
+static void
+vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
+		   struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
+		struct vmxnet3_tx_buf_info *tbi;
+		union Vmxnet3_GenericDesc *gdesc;
+
+		tbi = tq->buf_info + tq->tx_ring.next2comp;
+		gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
+
+		vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
+		if (tbi->skb) {
+			dev_kfree_skb_any(tbi->skb);
+			tbi->skb = NULL;
+		}
+		vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring);
+	}
+
+	/* sanity check, verify all buffers are indeed unmapped and freed */
+	for (i = 0; i < tq->tx_ring.size; i++) {
+		BUG_ON(tq->buf_info[i].skb != NULL ||
+		       tq->buf_info[i].map_type != VMXNET3_MAP_NONE);
+	}
+
+	tq->tx_ring.gen = VMXNET3_INIT_GEN;
+	tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0;
+
+	tq->comp_ring.gen = VMXNET3_INIT_GEN;
+	tq->comp_ring.next2proc = 0;
+}
+
+
+void
+vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq,
+		   struct vmxnet3_adapter *adapter)
+{
+	if (tq->tx_ring.base) {
+		pci_free_consistent(adapter->pdev, tq->tx_ring.size *
+				    sizeof(struct Vmxnet3_TxDesc),
+				    tq->tx_ring.base, tq->tx_ring.basePA);
+		tq->tx_ring.base = NULL;
+	}
+	if (tq->data_ring.base) {
+		pci_free_consistent(adapter->pdev, tq->data_ring.size *
+				    sizeof(struct Vmxnet3_TxDataDesc),
+				    tq->data_ring.base, tq->data_ring.basePA);
+		tq->data_ring.base = NULL;
+	}
+	if (tq->comp_ring.base) {
+		pci_free_consistent(adapter->pdev, tq->comp_ring.size *
+				    sizeof(struct Vmxnet3_TxCompDesc),
+				    tq->comp_ring.base, tq->comp_ring.basePA);
+		tq->comp_ring.base = NULL;
+	}
+	kfree(tq->buf_info);
+	tq->buf_info = NULL;
+}
+
+
+static void
+vmxnet3_tq_init(struct vmxnet3_tx_queue *tq,
+		struct vmxnet3_adapter *adapter)
+{
+	int i;
+
+	/* reset the tx ring contents to 0 and reset the tx ring states */
+	memset(tq->tx_ring.base, 0, tq->tx_ring.size *
+	       sizeof(struct Vmxnet3_TxDesc));
+	tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0;
+	tq->tx_ring.gen = VMXNET3_INIT_GEN;
+
+	memset(tq->data_ring.base, 0, tq->data_ring.size *
+	       sizeof(struct Vmxnet3_TxDataDesc));
+
+	/* reset the tx comp ring contents to 0 and reset comp ring states */
+	memset(tq->comp_ring.base, 0, tq->comp_ring.size *
+	       sizeof(struct Vmxnet3_TxCompDesc));
+	tq->comp_ring.next2proc = 0;
+	tq->comp_ring.gen = VMXNET3_INIT_GEN;
+
+	/* reset the bookkeeping data */
+	memset(tq->buf_info, 0, sizeof(tq->buf_info[0]) * tq->tx_ring.size);
+	for (i = 0; i < tq->tx_ring.size; i++)
+		tq->buf_info[i].map_type = VMXNET3_MAP_NONE;
+
+	/* stats are not reset */
+}
+
+
+static int
+vmxnet3_tq_create(struct vmxnet3_tx_queue *tq,
+		  struct vmxnet3_adapter *adapter)
+{
+	BUG_ON(tq->tx_ring.base || tq->data_ring.base ||
+	       tq->comp_ring.base || tq->buf_info);
+
+	tq->tx_ring.base = pci_alloc_consistent(adapter->pdev, tq->tx_ring.size
+			   * sizeof(struct Vmxnet3_TxDesc),
+			   &tq->tx_ring.basePA);
+	if (!tq->tx_ring.base) {
+		printk(KERN_ERR "%s: failed to allocate tx ring\n",
+		       adapter->netdev->name);
+		goto err;
+	}
+
+	tq->data_ring.base = pci_alloc_consistent(adapter->pdev,
+			     tq->data_ring.size *
+			     sizeof(struct Vmxnet3_TxDataDesc),
+			     &tq->data_ring.basePA);
+	if (!tq->data_ring.base) {
+		printk(KERN_ERR "%s: failed to allocate data ring\n",
+		       adapter->netdev->name);
+		goto err;
+	}
+
+	tq->comp_ring.base = pci_alloc_consistent(adapter->pdev,
+			     tq->comp_ring.size *
+			     sizeof(struct Vmxnet3_TxCompDesc),
+			     &tq->comp_ring.basePA);
+	if (!tq->comp_ring.base) {
+		printk(KERN_ERR "%s: failed to allocate tx comp ring\n",
+		       adapter->netdev->name);
+		goto err;
+	}
+
+	tq->buf_info = kcalloc(tq->tx_ring.size, sizeof(tq->buf_info[0]),
+			       GFP_KERNEL);
+	if (!tq->buf_info) {
+		printk(KERN_ERR "%s: failed to allocate tx bufinfo\n",
+		       adapter->netdev->name);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	vmxnet3_tq_destroy(tq, adapter);
+	return -ENOMEM;
+}
+
+
+/*
+ *    starting from ring->next2fill, allocate rx buffers for the given ring
+ *    of the rx queue and update the rx desc. stop after @num_to_alloc buffers
+ *    are allocated or allocation fails
+ */
+
+static int
+vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
+			int num_to_alloc, struct vmxnet3_adapter *adapter)
+{
+	int num_allocated = 0;
+	struct vmxnet3_rx_buf_info *rbi_base = rq->buf_info[ring_idx];
+	struct vmxnet3_cmd_ring *ring = &rq->rx_ring[ring_idx];
+	u32 val;
+
+	while (num_allocated < num_to_alloc) {
+		struct vmxnet3_rx_buf_info *rbi;
+		union Vmxnet3_GenericDesc *gd;
+
+		rbi = rbi_base + ring->next2fill;
+		gd = ring->base + ring->next2fill;
+
+		if (rbi->buf_type == VMXNET3_RX_BUF_SKB) {
+			if (rbi->skb == NULL) {
+				rbi->skb = dev_alloc_skb(rbi->len +
+							 NET_IP_ALIGN);
+				if (unlikely(rbi->skb == NULL)) {
+					rq->stats.rx_buf_alloc_failure++;
+					break;
+				}
+				rbi->skb->dev = adapter->netdev;
+
+				skb_reserve(rbi->skb, NET_IP_ALIGN);
+				rbi->dma_addr = pci_map_single(adapter->pdev,
+						rbi->skb->data, rbi->len,
+						PCI_DMA_FROMDEVICE);
+			} else {
+				/* rx buffer skipped by the device */
+			}
+			val = VMXNET3_RXD_BTYPE_HEAD << 
VMXNET3_RXD_BTYPE_SHIFT;
+		} else {
+			BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_PAGE ||
+			       rbi->len  != PAGE_SIZE);
+
+			if (rbi->page == NULL) {
+				rbi->page = alloc_page(GFP_ATOMIC);
+				if (unlikely(rbi->page == NULL)) {
+					rq->stats.rx_buf_alloc_failure++;
+					break;
+				}
+				rbi->dma_addr = pci_map_page(adapter->pdev,
+						rbi->page, 0, PAGE_SIZE,
+						PCI_DMA_FROMDEVICE);
+			} else {
+				/* rx buffers skipped by the device */
+			}
+			val = VMXNET3_RXD_BTYPE_BODY << 
VMXNET3_RXD_BTYPE_SHIFT;
+		}
+
+		BUG_ON(rbi->dma_addr == 0);
+		gd->rxd.addr = rbi->dma_addr;
+		gd->dword[2] = (ring->gen << VMXNET3_RXD_GEN_SHIFT) | val |
+				rbi->len;
+
+		num_allocated++;
+		vmxnet3_cmd_ring_adv_next2fill(ring);
+	}
+	rq->uncommitted[ring_idx] += num_allocated;
+
+	dprintk(KERN_ERR "alloc_rx_buf: %d allocated, next2fill %u, next2comp "
+		"%u, uncommited %u\n", num_allocated, ring->next2fill,
+		ring->next2comp, rq->uncommitted[ring_idx]);
+
+	/* so that the device can distinguish a full ring and an empty ring */
+	BUG_ON(num_allocated != 0 && ring->next2fill == ring->next2comp);
+
+	return num_allocated;
+}
+
+
+static void
+vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
+		    struct vmxnet3_rx_buf_info *rbi)
+{
+	struct skb_frag_struct *frag = skb_shinfo(skb)->frags +
+		skb_shinfo(skb)->nr_frags;
+
+	BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
+
+	frag->page = rbi->page;
+	frag->page_offset = 0;
+	frag->size = rcd->len;
+	skb->data_len += frag->size;
+	skb_shinfo(skb)->nr_frags++;
+}
+
+
+static void
+vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
+		struct vmxnet3_tx_queue *tq, struct pci_dev *pdev,
+		struct vmxnet3_adapter *adapter)
+{
+	u32 dw2, len;
+	unsigned long buf_offset;
+	int i;
+	union Vmxnet3_GenericDesc *gdesc;
+	struct vmxnet3_tx_buf_info *tbi = NULL;
+
+	BUG_ON(ctx->copy_size > skb_headlen(skb));
+
+	/* use the previous gen bit for the SOP desc */
+	dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT;
+
+	ctx->sop_txd = tq->tx_ring.base + tq->tx_ring.next2fill;
+	gdesc = ctx->sop_txd; /* both loops below can be skipped */
+
+	/* no need to map the buffer if headers are copied */
+	if (ctx->copy_size) {
+		ctx->sop_txd->txd.addr = tq->data_ring.basePA +
+					tq->tx_ring.next2fill *
+					sizeof(struct Vmxnet3_TxDataDesc);
+		ctx->sop_txd->dword[2] = dw2 | ctx->copy_size;
+		ctx->sop_txd->dword[3] = 0;
+
+		tbi = tq->buf_info + tq->tx_ring.next2fill;
+		tbi->map_type = VMXNET3_MAP_NONE;
+
+		dprintk(KERN_ERR "txd[%u]: 0x%Lx 0x%x 0x%x\n",
+			tq->tx_ring.next2fill, ctx->sop_txd->txd.addr,
+			ctx->sop_txd->dword[2], ctx->sop_txd->dword[3]);
+		vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+
+		/* use the right gen for non-SOP desc */
+		dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+	}
+
+	/* linear part can use multiple tx desc if it's big */
+	len = skb_headlen(skb) - ctx->copy_size;
+	buf_offset = ctx->copy_size;
+	while (len) {
+		u32 buf_size;
+
+		buf_size = len > VMXNET3_MAX_TX_BUF_SIZE ?
+			   VMXNET3_MAX_TX_BUF_SIZE : len;
+
+		tbi = tq->buf_info + tq->tx_ring.next2fill;
+		tbi->map_type = VMXNET3_MAP_SINGLE;
+		tbi->dma_addr = pci_map_single(adapter->pdev,
+				skb->data + buf_offset, buf_size,
+				PCI_DMA_TODEVICE);
+
+		tbi->len = buf_size; /* this automatically convert 2^14 to 0 */
+
+		gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+		BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+
+		gdesc->txd.addr = tbi->dma_addr;
+		gdesc->dword[2] = dw2 | buf_size;
+		gdesc->dword[3] = 0;
+
+		dprintk(KERN_ERR "txd[%u]: 0x%Lx 0x%x 0x%x\n",
+			tq->tx_ring.next2fill, gdesc->txd.addr,
+			gdesc->dword[2], gdesc->dword[3]);
+		vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+		dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+		len -= buf_size;
+		buf_offset += buf_size;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+		tbi = tq->buf_info + tq->tx_ring.next2fill;
+		tbi->map_type = VMXNET3_MAP_PAGE;
+		tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
+					     frag->page_offset, frag->size,
+					     PCI_DMA_TODEVICE);
+
+		tbi->len = frag->size;
+
+		gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+		BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+
+		gdesc->txd.addr = tbi->dma_addr;
+		gdesc->dword[2] = dw2 | frag->size;
+		gdesc->dword[3] = 0;
+
+		dprintk(KERN_ERR "txd[%u]: 0x%llu %u %u\n",
+			tq->tx_ring.next2fill, gdesc->txd.addr,
+			gdesc->dword[2], gdesc->dword[3]);
+		vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+		dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+	}
+
+	ctx->eop_txd = gdesc;
+
+	/* set the last buf_info for the pkt */
+	tbi->skb = skb;
+	tbi->sop_idx = ctx->sop_txd - tq->tx_ring.base;
+}
+
+
+/*
+ *    parse and copy relevant protocol headers:
+ *      For a tso pkt, relevant headers are L2/3/4 including options
+ *      For a pkt requesting csum offloading, they are L2/3 and may include L4
+ *      if it's a TCP/UDP pkt
+ *
+ * Returns:
+ *    -1:  error happens during parsing
+ *     0:  protocol headers parsed, but too big to be copied
+ *     1:  protocol headers parsed and copied
+ *
+ * Other effects:
+ *    1. related *ctx fields are updated.
+ *    2. ctx->copy_size is # of bytes copied
+ *    3. the portion copied is guaranteed to be in the linear part
+ *
+ */
+static int
+vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+			   struct vmxnet3_tx_ctx *ctx,
+			   struct vmxnet3_adapter *adapter)
+{
+	struct Vmxnet3_TxDataDesc *tdd;
+
+	if (ctx->mss) {
+		ctx->eth_ip_hdr_size = skb_transport_offset(skb);
+		ctx->l4_hdr_size = ((struct tcphdr *)
+				   skb_transport_header(skb))->doff * 4;
+		ctx->copy_size = ctx->eth_ip_hdr_size + ctx->l4_hdr_size;
+	} else {
+		unsigned int pull_size;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			ctx->eth_ip_hdr_size = skb_transport_offset(skb);
+
+			if (ctx->ipv4) {
+				struct iphdr *iph = (struct iphdr *)
+						    skb_network_header(skb);
+				if (iph->protocol == IPPROTO_TCP) {
+					pull_size = ctx->eth_ip_hdr_size +
+						    sizeof(struct tcphdr);
+
+					if (unlikely(!pskb_may_pull(skb,
+								pull_size))) {
+						goto err;
+					}
+					ctx->l4_hdr_size = ((struct tcphdr *)
+					   skb_transport_header(skb))->doff * 
4;
+				} else if (iph->protocol == IPPROTO_UDP) {
+					ctx->l4_hdr_size =
+							sizeof(struct udphdr);
+				} else {
+					ctx->l4_hdr_size = 0;
+				}
+			} else {
+				/* for simplicity, don't copy L4 headers */
+				ctx->l4_hdr_size = 0;
+			}
+			ctx->copy_size = ctx->eth_ip_hdr_size +
+					 ctx->l4_hdr_size;
+		} else {
+			ctx->eth_ip_hdr_size = 0;
+			ctx->l4_hdr_size = 0;
+			/* copy as much as allowed */
+			ctx->copy_size = min((unsigned 
int)VMXNET3_HDR_COPY_SIZE
+					     , skb_headlen(skb));
+		}
+
+		/* make sure headers are accessible directly */
+		if (unlikely(!pskb_may_pull(skb, ctx->copy_size)))
+			goto err;
+	}
+
+	if (unlikely(ctx->copy_size > VMXNET3_HDR_COPY_SIZE)) {
+		tq->stats.oversized_hdr++;
+		ctx->copy_size = 0;
+		return 0;
+	}
+
+	tdd = tq->data_ring.base + tq->tx_ring.next2fill;
+
+	memcpy(tdd->data, skb->data, ctx->copy_size);
+	dprintk(KERN_ERR "copy %u bytes to dataRing[%u]\n",
+		ctx->copy_size, tq->tx_ring.next2fill);
+	return 1;
+
+err:
+	return -1;
+}
+
+
+static void
+vmxnet3_prepare_tso(struct sk_buff *skb,
+		    struct vmxnet3_tx_ctx *ctx)
+{
+	struct tcphdr *tcph = (struct tcphdr *)skb_transport_header(skb);
+	if (ctx->ipv4) {
+		struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
+		iph->check = 0;
+		tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0,
+						 IPPROTO_TCP, 0);
+	} else {
+		struct ipv6hdr *iph = (struct ipv6hdr 
*)skb_network_header(skb);
+		tcph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, 0,
+					       IPPROTO_TCP, 0);
+	}
+}
+
+
+/*
+ * Transmits a pkt thru a given tq
+ * Returns:
+ *    NETDEV_TX_OK:      descriptors are setup successfully
+ *    NETDEV_TX_OK:      error occured, the pkt is dropped
+ *    NETDEV_TX_BUSY:    tx ring is full, queue is stopped
+ *
+ * Side-effects:
+ *    1. tx ring may be changed
+ *    2. tq stats may be updated accordingly
+ *    3. shared->txNumDeferred may be updated
+ */
+
+static int
+vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+		struct vmxnet3_adapter *adapter, struct net_device *netdev)
+{
+	int ret;
+	u32 count;
+	unsigned long flags;
+	struct vmxnet3_tx_ctx ctx;
+	union Vmxnet3_GenericDesc *gdesc;
+
+	/* conservatively estimate # of descriptors to use */
+	count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
+		skb_shinfo(skb)->nr_frags + 1;
+
+	ctx.ipv4 = (skb->protocol == __constant_ntohs(ETH_P_IP));
+
+	ctx.mss = skb_shinfo(skb)->gso_size;
+	if (ctx.mss) {
+		if (skb_header_cloned(skb)) {
+			if (unlikely(pskb_expand_head(skb, 0, 0,
+						      GFP_ATOMIC) != 0)) {
+				tq->stats.drop_tso++;
+				goto drop_pkt;
+			}
+			tq->stats.copy_skb_header++;
+		}
+		vmxnet3_prepare_tso(skb, &ctx);
+	} else {
+		if (unlikely(count > VMXNET3_MAX_TXD_PER_PKT)) {
+
+			/* non-tso pkts must not use more than
+			 * VMXNET3_MAX_TXD_PER_PKT entries
+			 */
+			if (skb_linearize(skb) != 0) {
+				tq->stats.drop_too_many_frags++;
+				goto drop_pkt;
+			}
+			tq->stats.linearized++;
+
+			/* recalculate the # of descriptors to use */
+			count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+		}
+	}
+
+	ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx, adapter);
+	if (ret >= 0) {
+		BUG_ON(ret <= 0 && ctx.copy_size != 0);
+		/* hdrs parsed, check against other limits */
+		if (ctx.mss) {
+			if (unlikely(ctx.eth_ip_hdr_size + ctx.l4_hdr_size >
+				     VMXNET3_MAX_TX_BUF_SIZE)) {
+				goto hdr_too_big;
+			}
+		} else {
+			if (skb->ip_summed == CHECKSUM_PARTIAL) {
+				if (unlikely(ctx.eth_ip_hdr_size +
+					     skb->csum_offset >
+					     VMXNET3_MAX_CSUM_OFFSET)) {
+					goto hdr_too_big;
+				}
+			}
+		}
+	} else {
+		tq->stats.drop_hdr_inspect_err++;
+		goto drop_pkt;
+	}
+
+	spin_lock_irqsave(&tq->tx_lock, flags);
+
+	if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
+		tq->stats.tx_ring_full++;
+		dprintk(KERN_ERR "tx queue stopped on %s, next2comp %u"
+			" next2fill %u\n", adapter->netdev->name,
+			tq->tx_ring.next2comp, tq->tx_ring.next2fill);
+
+		vmxnet3_tq_stop(tq, adapter);
+		spin_unlock_irqrestore(&tq->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	/* fill tx descs related to addr & len */
+	vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter);
+
+	/* setup the EOP desc */
+	ctx.eop_txd->dword[3] = VMXNET3_TXD_CQ | VMXNET3_TXD_EOP;
+
+	/* setup the SOP desc */
+	gdesc = ctx.sop_txd;
+	if (ctx.mss) {
+		gdesc->txd.hlen = ctx.eth_ip_hdr_size + ctx.l4_hdr_size;
+		gdesc->txd.om = VMXNET3_OM_TSO;
+		gdesc->txd.msscof = ctx.mss;
+		tq->shared->txNumDeferred += (skb->len - gdesc->txd.hlen +
+					     ctx.mss - 1) / ctx.mss;
+	} else {
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			gdesc->txd.hlen = ctx.eth_ip_hdr_size;
+			gdesc->txd.om = VMXNET3_OM_CSUM;
+			gdesc->txd.msscof = ctx.eth_ip_hdr_size +
+					    skb->csum_offset;
+		} else {
+			gdesc->txd.om = 0;
+			gdesc->txd.msscof = 0;
+		}
+		tq->shared->txNumDeferred++;
+	}
+
+	if (vlan_tx_tag_present(skb)) {
+		gdesc->txd.ti = 1;
+		gdesc->txd.tci = vlan_tx_tag_get(skb);
+	}
+
+	wmb();
+
+	/* finally flips the GEN bit of the SOP desc */
+	gdesc->dword[2] ^= VMXNET3_TXD_GEN;
+	dprintk(KERN_ERR "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n",
+		(u32)((union Vmxnet3_GenericDesc *)ctx.sop_txd -
+		tq->tx_ring.base), gdesc->txd.addr, gdesc->dword[2],
+		gdesc->dword[3]);
+
+	spin_unlock_irqrestore(&tq->tx_lock, flags);
+
+	if (tq->shared->txNumDeferred >= tq->shared->txThreshold) {
+		tq->shared->txNumDeferred = 0;
+		VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD,
+				       tq->tx_ring.next2fill);
+	}
+	netdev->trans_start = jiffies;
+
+	return NETDEV_TX_OK;
+
+hdr_too_big:
+	tq->stats.drop_oversized_hdr++;
+drop_pkt:
+	tq->stats.drop_total++;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+
+static netdev_tx_t
+vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct vmxnet3_tx_queue *tq = &adapter->tx_queue;
+
+	return vmxnet3_tq_xmit(skb, tq, adapter, netdev);
+}
+
+
+static void
+vmxnet3_rx_csum(struct vmxnet3_adapter *adapter,
+		struct sk_buff *skb,
+		union Vmxnet3_GenericDesc *gdesc)
+{
+	if (!gdesc->rcd.cnc && adapter->rxcsum) {
+		/* typical case: TCP/UDP over IP and both csums are correct */
+		if ((gdesc->dword[3] & VMXNET3_RCD_CSUM_OK) ==
+							VMXNET3_RCD_CSUM_OK) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			BUG_ON(!(gdesc->rcd.tcp || gdesc->rcd.udp));
+			BUG_ON(!(gdesc->rcd.v4  || gdesc->rcd.v6));
+			BUG_ON(gdesc->rcd.frg);
+		} else {
+			if (gdesc->rcd.csum) {
+				skb->csum = htons(gdesc->rcd.csum);
+				skb->ip_summed = CHECKSUM_PARTIAL;
+			} else {
+				skb->ip_summed = CHECKSUM_NONE;
+			}
+		}
+	} else {
+		skb->ip_summed = CHECKSUM_NONE;
+	}
+}
+
+
+static void
+vmxnet3_rx_error(struct vmxnet3_rx_queue *rq, struct Vmxnet3_RxCompDesc *rcd,
+		 struct vmxnet3_rx_ctx *ctx,  struct vmxnet3_adapter *adapter)
+{
+	rq->stats.drop_err++;
+	if (!rcd->fcs)
+		rq->stats.drop_fcs++;
+
+	rq->stats.drop_total++;
+
+	/*
+	 * We do not unmap and chain the rx buffer to the skb.
+	 * We basically pretend this buffer is not used and will be recycled
+	 * by vmxnet3_rq_alloc_rx_buf()
+	 */
+
+	/*
+	 * ctx->skb may be NULL if this is the first and the only one
+	 * desc for the pkt
+	 */
+	if (ctx->skb)
+		dev_kfree_skb_irq(ctx->skb);
+
+	ctx->skb = NULL;
+}
+
+
+static int
+vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
+		       struct vmxnet3_adapter *adapter, int quota)
+{
+	static u32 rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2};
+	u32 num_rxd = 0;
+	struct Vmxnet3_RxCompDesc *rcd;
+	struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
+
+	rcd = &rq->comp_ring.base[rq->comp_ring.next2proc].rcd;
+	while (rcd->gen == rq->comp_ring.gen) {
+		struct vmxnet3_rx_buf_info *rbi;
+		struct sk_buff *skb;
+		int num_to_alloc;
+		struct Vmxnet3_RxDesc *rxd;
+		u32 idx, ring_idx;
+
+		if (num_rxd >= quota) {
+			/* we may stop even before we see the EOP desc of
+			 * the current pkt
+			 */
+			break;
+		}
+		num_rxd++;
+
+		idx = rcd->rxdIdx;
+		ring_idx = rcd->rqID == rq->qid ? 0 : 1;
+
+		rxd = &rq->rx_ring[ring_idx].base[idx].rxd;
+		rbi = rq->buf_info[ring_idx] + idx;
+
+		BUG_ON(rxd->addr != rbi->dma_addr || rxd->len != rbi->len);
+
+		if (unlikely(rcd->eop && rcd->err)) {
+			vmxnet3_rx_error(rq, rcd, ctx, adapter);
+			goto rcd_done;
+		}
+
+		if (rcd->sop) { /* first buf of the pkt */
+			BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_HEAD ||
+			       rcd->rqID != rq->qid);
+
+			BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB);
+			BUG_ON(ctx->skb != NULL || rbi->skb == NULL);
+
+			if (unlikely(rcd->len == 0)) {
+				/* Pretend the rx buffer is skipped. */
+				BUG_ON(!(rcd->sop && rcd->eop));
+				dprintk(KERN_ERR "rxRing[%u][%u] 0 length\n",
+					ring_idx, idx);
+				goto rcd_done;
+			}
+
+			ctx->skb = rbi->skb;
+			rbi->skb = NULL;
+
+			pci_unmap_single(adapter->pdev, rbi->dma_addr, 
rbi->len,
+					 PCI_DMA_FROMDEVICE);
+
+			skb_put(ctx->skb, rcd->len);
+		} else {
+			BUG_ON(ctx->skb == NULL);
+			/* non SOP buffer must be type 1 in most cases */
+			if (rbi->buf_type == VMXNET3_RX_BUF_PAGE) {
+				BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_BODY);
+
+				if (rcd->len) {
+					pci_unmap_page(adapter->pdev,
+						       rbi->dma_addr, rbi->len,
+						       PCI_DMA_FROMDEVICE);
+
+					vmxnet3_append_frag(ctx->skb, rcd, 
rbi);
+					rbi->page = NULL;
+				}
+			} else {
+				/*
+				 * The only time a non-SOP buffer is type 0 is
+				 * when it's EOP and error flag is raised, 
which
+				 * has already been handled.
+				 */
+				BUG_ON(true);
+			}
+		}
+
+		skb = ctx->skb;
+		if (rcd->eop) {
+			skb->len += skb->data_len;
+			skb->truesize += skb->data_len;
+
+			vmxnet3_rx_csum(adapter, skb,
+					(union Vmxnet3_GenericDesc *)rcd);
+			skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+			if (unlikely(adapter->vlan_grp && rcd->ts)) {
+				vlan_hwaccel_receive_skb(skb,
+						adapter->vlan_grp, rcd->tci);
+			} else {
+				netif_receive_skb(skb);
+			}
+
+			adapter->netdev->last_rx = jiffies;
+			ctx->skb = NULL;
+		}
+
+rcd_done:
+		/* device may skip some rx descs */
+		rq->rx_ring[ring_idx].next2comp = idx;
+		VMXNET3_INC_RING_IDX_ONLY(rq->rx_ring[ring_idx].next2comp,
+					  rq->rx_ring[ring_idx].size);
+
+		/* refill rx buffers frequently to avoid starving the h/w */
+		num_to_alloc = vmxnet3_cmd_ring_desc_avail(rq->rx_ring +
+							   ring_idx);
+		if (unlikely(num_to_alloc > VMXNET3_RX_ALLOC_THRESHOLD(rq,
+							ring_idx, adapter))) {
+			vmxnet3_rq_alloc_rx_buf(rq, ring_idx, num_to_alloc,
+						adapter);
+
+			/* if needed, update the register */
+			if (unlikely(rq->shared->updateRxProd)) {
+				VMXNET3_WRITE_BAR0_REG(adapter,
+					rxprod_reg[ring_idx] + rq->qid * 8,
+					rq->rx_ring[ring_idx].next2fill);
+				rq->uncommitted[ring_idx] = 0;
+			}
+		}
+
+		vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
+		rcd = &rq->comp_ring.base[rq->comp_ring.next2proc].rcd;
+	}
+
+	return num_rxd;
+}
+
+
+static void
+vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
+		   struct vmxnet3_adapter *adapter)
+{
+	u32 i, ring_idx;
+	struct Vmxnet3_RxDesc *rxd;
+
+	for (ring_idx = 0; ring_idx < 2; ring_idx++) {
+		for (i = 0; i < rq->rx_ring[ring_idx].size; i++) {
+			rxd = &rq->rx_ring[ring_idx].base[i].rxd;
+
+			if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD &&
+					rq->buf_info[ring_idx][i].skb) {
+				pci_unmap_single(adapter->pdev, rxd->addr,
+						 rxd->len, PCI_DMA_FROMDEVICE);
+				dev_kfree_skb(rq->buf_info[ring_idx][i].skb);
+				rq->buf_info[ring_idx][i].skb = NULL;
+			} else if (rxd->btype == VMXNET3_RXD_BTYPE_BODY &&
+					rq->buf_info[ring_idx][i].page) {
+				pci_unmap_page(adapter->pdev, rxd->addr,
+					       rxd->len, PCI_DMA_FROMDEVICE);
+				put_page(rq->buf_info[ring_idx][i].page);
+				rq->buf_info[ring_idx][i].page = NULL;
+			}
+		}
+
+		rq->rx_ring[ring_idx].gen = VMXNET3_INIT_GEN;
+		rq->rx_ring[ring_idx].next2fill =
+					rq->rx_ring[ring_idx].next2comp = 0;
+		rq->uncommitted[ring_idx] = 0;
+	}
+
+	rq->comp_ring.gen = VMXNET3_INIT_GEN;
+	rq->comp_ring.next2proc = 0;
+}
+
+
+void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq,
+			struct vmxnet3_adapter *adapter)
+{
+	int i;
+	int j;
+
+	/* all rx buffers must have already been freed */
+	for (i = 0; i < 2; i++) {
+		if (rq->buf_info[i]) {
+			for (j = 0; j < rq->rx_ring[i].size; j++)
+				BUG_ON(rq->buf_info[i][j].page != NULL);
+		}
+	}
+
+
+	kfree(rq->buf_info[0]);
+
+	for (i = 0; i < 2; i++) {
+		if (rq->rx_ring[i].base) {
+			pci_free_consistent(adapter->pdev, rq->rx_ring[i].size
+					    * sizeof(struct Vmxnet3_RxDesc),
+					    rq->rx_ring[i].base,
+					    rq->rx_ring[i].basePA);
+			rq->rx_ring[i].base = NULL;
+		}
+		rq->buf_info[i] = NULL;
+	}
+
+	if (rq->comp_ring.base) {
+		pci_free_consistent(adapter->pdev, rq->comp_ring.size *
+				    sizeof(struct Vmxnet3_RxCompDesc),
+				    rq->comp_ring.base, rq->comp_ring.basePA);
+		rq->comp_ring.base = NULL;
+	}
+}
+
+
+static int
+vmxnet3_rq_init(struct vmxnet3_rx_queue *rq,
+		struct vmxnet3_adapter  *adapter)
+{
+	int i;
+
+	/* initialize buf_info */
+	for (i = 0; i < rq->rx_ring[0].size; i++) {
+
+		/* 1st buf for a pkt is skbuff */
+		if (i % adapter->rx_buf_per_pkt == 0) {
+			rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_SKB;
+			rq->buf_info[0][i].len = adapter->skb_buf_size;
+		} else { /* subsequent bufs for a pkt is frag */
+			rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_PAGE;
+			rq->buf_info[0][i].len = PAGE_SIZE;
+		}
+	}
+	for (i = 0; i < rq->rx_ring[1].size; i++) {
+		rq->buf_info[1][i].buf_type = VMXNET3_RX_BUF_PAGE;
+		rq->buf_info[1][i].len = PAGE_SIZE;
+	}
+
+	/* reset internal state and allocate buffers for both rings */
+	for (i = 0; i < 2; i++) {
+		rq->rx_ring[i].next2fill = rq->rx_ring[i].next2comp = 0;
+		rq->uncommitted[i] = 0;
+
+		memset(rq->rx_ring[i].base, 0, rq->rx_ring[i].size *
+		       sizeof(struct Vmxnet3_RxDesc));
+		rq->rx_ring[i].gen = VMXNET3_INIT_GEN;
+	}
+	if (vmxnet3_rq_alloc_rx_buf(rq, 0, rq->rx_ring[0].size - 1,
+				    adapter) == 0) {
+		/* at least has 1 rx buffer for the 1st ring */
+		return -ENOMEM;
+	}
+	vmxnet3_rq_alloc_rx_buf(rq, 1, rq->rx_ring[1].size - 1, adapter);
+
+	/* reset the comp ring */
+	rq->comp_ring.next2proc = 0;
+	memset(rq->comp_ring.base, 0, rq->comp_ring.size *
+	       sizeof(struct Vmxnet3_RxCompDesc));
+	rq->comp_ring.gen = VMXNET3_INIT_GEN;
+
+	/* reset rxctx */
+	rq->rx_ctx.skb = NULL;
+
+	/* stats are not reset */
+	return 0;
+}
+
+
+static int
+vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter 
*adapter)
+{
+	int i;
+	size_t sz;
+	struct vmxnet3_rx_buf_info *bi;
+
+	for (i = 0; i < 2; i++) {
+
+		sz = rq->rx_ring[i].size * sizeof(struct Vmxnet3_RxDesc);
+		rq->rx_ring[i].base = pci_alloc_consistent(adapter->pdev, sz,
+ 
&rq->rx_ring[i].basePA);
+		if (!rq->rx_ring[i].base) {
+			printk(KERN_ERR "%s: failed to allocate rx ring %d\n",
+			       adapter->netdev->name, i);
+			goto err;
+		}
+	}
+
+	sz = rq->comp_ring.size * sizeof(struct Vmxnet3_RxCompDesc);
+	rq->comp_ring.base = pci_alloc_consistent(adapter->pdev, sz,
+						  &rq->comp_ring.basePA);
+	if (!rq->comp_ring.base) {
+		printk(KERN_ERR "%s: failed to allocate rx comp ring\n",
+		       adapter->netdev->name);
+		goto err;
+	}
+
+	sz = sizeof(struct vmxnet3_rx_buf_info) * (rq->rx_ring[0].size +
+						   rq->rx_ring[1].size);
+	bi = kmalloc(sz, GFP_KERNEL);
+	if (!bi) {
+		printk(KERN_ERR "%s: failed to allocate rx bufinfo\n",
+		       adapter->netdev->name);
+		goto err;
+	}
+	memset(bi, 0, sz);
+	rq->buf_info[0] = bi;
+	rq->buf_info[1] = bi + rq->rx_ring[0].size;
+
+	return 0;
+
+err:
+	vmxnet3_rq_destroy(rq, adapter);
+	return -ENOMEM;
+}
+
+
+static void
+vmxnet3_do_poll(struct vmxnet3_adapter *adapter, int budget, int *txd_done,
+		int *rxd_done)
+{
+	if (unlikely(adapter->shared->ecr))
+		vmxnet3_process_events(adapter);
+
+	*txd_done = vmxnet3_tq_tx_complete(&adapter->tx_queue, adapter);
+	*rxd_done = vmxnet3_rq_rx_complete(&adapter->rx_queue, adapter, 
budget);
+}
+
+
+static int
+vmxnet3_poll(struct napi_struct *napi, int budget)
+{
+	struct vmxnet3_adapter *adapter = container_of(napi,
+					  struct vmxnet3_adapter, napi);
+	int rxd_done, txd_done;
+
+	vmxnet3_do_poll(adapter, budget, &txd_done, &rxd_done);
+
+	if (rxd_done < budget) {
+		napi_complete(napi);
+		vmxnet3_enable_intr(adapter, 0);
+	}
+	return rxd_done;
+}
+
+
+/* Interrupt handler for vmxnet3  */
+static irqreturn_t
+vmxnet3_intr(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct vmxnet3_adapter *adapter = netdev_priv(dev);
+
+	if (unlikely(adapter->intr.type == VMXNET3_IT_INTX)) {
+		u32 icr = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ICR);
+		if (unlikely(icr == 0))
+			/* not ours */
+			return IRQ_NONE;
+	}
+
+
+	/* disable intr if needed */
+	if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
+		vmxnet3_disable_intr(adapter, 0);
+
+	napi_schedule(&adapter->napi);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+
+/* netpoll callback. */
+static void
+vmxnet3_netpoll(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	int irq;
+
+	if (adapter->intr.type == VMXNET3_IT_MSIX)
+		irq = adapter->intr.msix_entries[0].vector;
+	else
+		irq = adapter->pdev->irq;
+
+	disable_irq(irq);
+	vmxnet3_intr(irq, netdev);
+	enable_irq(irq);
+}
+#endif
+
+static int
+vmxnet3_request_irqs(struct vmxnet3_adapter *adapter)
+{
+	int err;
+
+	if (adapter->intr.type == VMXNET3_IT_MSIX) {
+		/* we only use 1 MSI-X vector */
+		err = request_irq(adapter->intr.msix_entries[0].vector,
+				  vmxnet3_intr, 0, adapter->netdev->name,
+				  adapter->netdev);
+	} else if (adapter->intr.type == VMXNET3_IT_MSI) {
+		err = request_irq(adapter->pdev->irq, vmxnet3_intr, 0,
+				  adapter->netdev->name, adapter->netdev);
+	} else {
+		err = request_irq(adapter->pdev->irq, vmxnet3_intr,
+				  IRQF_SHARED, adapter->netdev->name,
+				  adapter->netdev);
+	}
+
+	if (err)
+		printk(KERN_ERR "Failed to request irq %s (intr type:%d), 
error"
+		       ":%d\n", adapter->netdev->name, adapter->intr.type, 
err);
+
+
+	if (!err) {
+		int i;
+		/* init our intr settings */
+		for (i = 0; i < adapter->intr.num_intrs; i++)
+			adapter->intr.mod_levels[i] = UPT1_IML_ADAPTIVE;
+
+		/* next setup intr index for all intr sources */
+		adapter->tx_queue.comp_ring.intr_idx = 0;
+		adapter->rx_queue.comp_ring.intr_idx = 0;
+		adapter->intr.event_intr_idx = 0;
+
+		printk(KERN_INFO "%s: intr type %u, mode %u, %u vectors "
+		       "allocated\n", adapter->netdev->name, 
adapter->intr.type,
+		       adapter->intr.mask_mode, adapter->intr.num_intrs);
+	}
+
+	return err;
+}
+
+
+static void
+vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
+{
+	BUG_ON(adapter->intr.type == VMXNET3_IT_AUTO ||
+	       adapter->intr.num_intrs <= 0);
+
+	switch (adapter->intr.type) {
+	case VMXNET3_IT_MSIX:
+	{
+		int i;
+
+		for (i = 0; i < adapter->intr.num_intrs; i++)
+			free_irq(adapter->intr.msix_entries[i].vector,
+				 adapter->netdev);
+		break;
+	}
+	case VMXNET3_IT_MSI:
+		free_irq(adapter->pdev->irq, adapter->netdev);
+		break;
+	case VMXNET3_IT_INTX:
+		free_irq(adapter->pdev->irq, adapter->netdev);
+		break;
+	default:
+		BUG_ON(true);
+	}
+}
+
+
+static void
+vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct Vmxnet3_DriverShared *shared = adapter->shared;
+	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+
+	if (grp) {
+		/* add vlan rx stripping. */
+		if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
+			int i;
+			struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
+			adapter->vlan_grp = grp;
+
+			/* update FEATURES to device */
+			devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
+			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+					       VMXNET3_CMD_UPDATE_FEATURE);
+			/*
+			 *  Clear entire vfTable; then enable untagged pkts.
+			 *  Note: setting one entry in vfTable to non-zero 
turns
+			 *  on VLAN rx filtering.
+			 */
+			for (i = 0; i < VMXNET3_VFT_SIZE; i++)
+				vfTable[i] = 0;
+
+			VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ 
VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+		} else {
+			printk(KERN_ERR "%s: vlan_rx_register when device has "
+			       "no NETIF_F_HW_VLAN_RX\n", netdev->name);
+		}
+	} else {
+		/* remove vlan rx stripping. */
+		struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
+		adapter->vlan_grp = NULL;
+
+		if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
+			int i;
+
+			for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
+				/* clear entire vfTable; this also disables
+				 * VLAN rx filtering
+				 */
+				vfTable[i] = 0;
+			}
+			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ 
VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+
+			/* update FEATURES to device */
+			devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN;
+			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+					       VMXNET3_CMD_UPDATE_FEATURE);
+		}
+	}
+}
+
+
+static void
+vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
+{
+	if (adapter->vlan_grp) {
+		u16 vid;
+		u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+		bool activeVlan = false;
+
+		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+			if (vlan_group_get_device(adapter->vlan_grp, vid)) {
+				VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+				activeVlan = true;
+			}
+		}
+		if (activeVlan) {
+			/* continue to allow untagged pkts */
+			VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+		}
+	}
+}
+
+
+static void
+vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+
+	VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+}
+
+
+static void
+vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+
+	VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+}
+
+
+static u8 *
+vmxnet3_copy_mc(struct net_device *netdev)
+{
+	u8 *buf = NULL;
+	u32 sz = netdev->mc_count * ETH_ALEN;
+
+	/* struct Vmxnet3_RxFilterConf.mfTableLen is u16. */
+	if (sz <= 0xffff) {
+		/* We may be called with BH disabled */
+		buf = kmalloc(sz, GFP_ATOMIC);
+		if (buf) {
+			int i;
+			struct dev_mc_list *mc = netdev->mc_list;
+
+			for (i = 0; i < netdev->mc_count; i++) {
+				BUG_ON(!mc);
+				memcpy(buf + i * ETH_ALEN, mc->dmi_addr,
+				       ETH_ALEN);
+				mc = mc->next;
+			}
+		}
+	}
+	return buf;
+}
+
+
+static void
+vmxnet3_set_mc(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct Vmxnet3_RxFilterConf *rxConf =
+					&adapter->shared->devRead.rxFilterConf;
+	u8 *new_table = NULL;
+	u32 new_mode = VMXNET3_RXM_UCAST;
+
+	if (netdev->flags & IFF_PROMISC)
+		new_mode |= VMXNET3_RXM_PROMISC;
+
+	if (netdev->flags & IFF_BROADCAST)
+		new_mode |= VMXNET3_RXM_BCAST;
+
+	if (netdev->flags & IFF_ALLMULTI)
+		new_mode |= VMXNET3_RXM_ALL_MULTI;
+	else
+		if (netdev->mc_count > 0) {
+			new_table = vmxnet3_copy_mc(netdev);
+			if (new_table) {
+				new_mode |= VMXNET3_RXM_MCAST;
+				rxConf->mfTableLen = netdev->mc_count *
+						     ETH_ALEN;
+				rxConf->mfTablePA = virt_to_phys(new_table);
+			} else {
+				printk(KERN_INFO "%s: failed to copy mcast 
list"
+				       ", setting ALL_MULTI\n", netdev->name);
+				new_mode |= VMXNET3_RXM_ALL_MULTI;
+			}
+		}
+
+
+	if (!(new_mode & VMXNET3_RXM_MCAST)) {
+		rxConf->mfTableLen = 0;
+		rxConf->mfTablePA = 0;
+	}
+
+	if (new_mode != rxConf->rxMode) {
+		rxConf->rxMode = new_mode;
+		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+				       VMXNET3_CMD_UPDATE_RX_MODE);
+	}
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_UPDATE_MAC_FILTERS);
+
+	kfree(new_table);
+}
+
+
+/*
+ *   Set up driver_shared based on settings in adapter.
+ */
+
+static void
+vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
+{
+	struct Vmxnet3_DriverShared *shared = adapter->shared;
+	struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
+	struct Vmxnet3_TxQueueConf *tqc;
+	struct Vmxnet3_RxQueueConf *rqc;
+	int i;
+
+	memset(shared, 0, sizeof(*shared));
+
+	/* driver settings */
+	shared->magic = VMXNET3_REV1_MAGIC;
+	devRead->misc.driverInfo.version = VMXNET3_DRIVER_VERSION_NUM;
+	devRead->misc.driverInfo.gos.gosBits = (sizeof(void *) == 4 ?
+				VMXNET3_GOS_BITS_32 : VMXNET3_GOS_BITS_64);
+	devRead->misc.driverInfo.gos.gosType = VMXNET3_GOS_TYPE_LINUX;
+	devRead->misc.driverInfo.vmxnet3RevSpt = 1;
+	devRead->misc.driverInfo.uptVerSpt = 1;
+
+	devRead->misc.ddPA = virt_to_phys(adapter);
+	devRead->misc.ddLen = sizeof(struct vmxnet3_adapter);
+
+	/* set up feature flags */
+	if (adapter->rxcsum)
+		devRead->misc.uptFeatures |= UPT1_F_RXCSUM;
+
+	if (adapter->lro) {
+		devRead->misc.uptFeatures |= UPT1_F_LRO;
+		devRead->misc.maxNumRxSG = 1 + MAX_SKB_FRAGS;
+	}
+	if ((adapter->netdev->features & NETIF_F_HW_VLAN_RX)
+			&& adapter->vlan_grp) {
+		devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
+	}
+
+	devRead->misc.mtu = adapter->netdev->mtu;
+	devRead->misc.queueDescPA = adapter->queue_desc_pa;
+	devRead->misc.queueDescLen = sizeof(struct Vmxnet3_TxQueueDesc) +
+				     sizeof(struct Vmxnet3_RxQueueDesc);
+
+	/* tx queue settings */
+	BUG_ON(adapter->tx_queue.tx_ring.base == NULL);
+
+	devRead->misc.numTxQueues = 1;
+	tqc = &adapter->tqd_start->conf;
+	tqc->txRingBasePA   = adapter->tx_queue.tx_ring.basePA;
+	tqc->dataRingBasePA = adapter->tx_queue.data_ring.basePA;
+	tqc->compRingBasePA = adapter->tx_queue.comp_ring.basePA;
+	tqc->ddPA           = virt_to_phys(adapter->tx_queue.buf_info);
+	tqc->txRingSize     = adapter->tx_queue.tx_ring.size;
+	tqc->dataRingSize   = adapter->tx_queue.data_ring.size;
+	tqc->compRingSize   = adapter->tx_queue.comp_ring.size;
+	tqc->ddLen          = sizeof(struct vmxnet3_tx_buf_info) *
+			      tqc->txRingSize;
+	tqc->intrIdx        = adapter->tx_queue.comp_ring.intr_idx;
+
+	/* rx queue settings */
+	devRead->misc.numRxQueues = 1;
+	rqc = &adapter->rqd_start->conf;
+	rqc->rxRingBasePA[0] = adapter->rx_queue.rx_ring[0].basePA;
+	rqc->rxRingBasePA[1] = adapter->rx_queue.rx_ring[1].basePA;
+	rqc->compRingBasePA  = adapter->rx_queue.comp_ring.basePA;
+	rqc->ddPA            = virt_to_phys(adapter->rx_queue.buf_info);
+	rqc->rxRingSize[0]   = adapter->rx_queue.rx_ring[0].size;
+	rqc->rxRingSize[1]   = adapter->rx_queue.rx_ring[1].size;
+	rqc->compRingSize    = adapter->rx_queue.comp_ring.size;
+	rqc->ddLen           = sizeof(struct vmxnet3_rx_buf_info) *
+			       (rqc->rxRingSize[0] + rqc->rxRingSize[1]);
+	rqc->intrIdx         = adapter->rx_queue.comp_ring.intr_idx;
+
+	/* intr settings */
+	devRead->intrConf.autoMask = adapter->intr.mask_mode ==
+				     VMXNET3_IMM_AUTO;
+	devRead->intrConf.numIntrs = adapter->intr.num_intrs;
+	for (i = 0; i < adapter->intr.num_intrs; i++)
+		devRead->intrConf.modLevels[i] = adapter->intr.mod_levels[i];
+
+	devRead->intrConf.eventIntrIdx = adapter->intr.event_intr_idx;
+
+	/* rx filter settings */
+	devRead->rxFilterConf.rxMode = 0;
+	vmxnet3_restore_vlan(adapter);
+	/* the rest are already zeroed */
+}
+
+
+int
+vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
+{
+	int err;
+	u32 ret;
+
+	dprintk(KERN_ERR "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes"
+		" %u %u %u\n", adapter->netdev->name, adapter->skb_buf_size,
+		adapter->rx_buf_per_pkt, adapter->tx_queue.tx_ring.size,
+		adapter->rx_queue.rx_ring[0].size,
+		adapter->rx_queue.rx_ring[1].size);
+
+	vmxnet3_tq_init(&adapter->tx_queue, adapter);
+	err = vmxnet3_rq_init(&adapter->rx_queue, adapter);
+	if (err) {
+		printk(KERN_ERR "Failed to init rx queue for %s: error %d\n",
+		       adapter->netdev->name, err);
+		goto rq_err;
+	}
+
+	err = vmxnet3_request_irqs(adapter);
+	if (err) {
+		printk(KERN_ERR "Failed to setup irq for %s: error %d\n",
+		       adapter->netdev->name, err);
+		goto irq_err;
+	}
+
+	vmxnet3_setup_driver_shared(adapter);
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAL,
+			       VMXNET3_GET_ADDR_LO(adapter->shared_pa));
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH,
+			       VMXNET3_GET_ADDR_HI(adapter->shared_pa));
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_ACTIVATE_DEV);
+	ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to activate dev %s: error %u\n",
+		       adapter->netdev->name, ret);
+		err = -EINVAL;
+		goto activate_err;
+	}
+	VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD,
+			       adapter->rx_queue.rx_ring[0].next2fill);
+	VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD2,
+			       adapter->rx_queue.rx_ring[1].next2fill);
+
+	/* Apply the rx filter settins last. */
+	vmxnet3_set_mc(adapter->netdev);
+
+	/*
+	 * Check link state when first activating device. It will start the
+	 * tx queue if the link is up.
+	 */
+	vmxnet3_check_link(adapter);
+
+	napi_enable(&adapter->napi);
+	vmxnet3_enable_all_intrs(adapter);
+	clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
+	return 0;
+
+activate_err:
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAL, 0);
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, 0);
+	vmxnet3_free_irqs(adapter);
+irq_err:
+rq_err:
+	/* free up buffers we allocated */
+	vmxnet3_rq_cleanup(&adapter->rx_queue, adapter);
+	return err;
+}
+
+
+void
+vmxnet3_reset_dev(struct vmxnet3_adapter *adapter)
+{
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, 
VMXNET3_CMD_RESET_DEV);
+}
+
+
+int
+vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter)
+{
+	if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))
+		return 0;
+
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_QUIESCE_DEV);
+	vmxnet3_disable_all_intrs(adapter);
+
+	napi_disable(&adapter->napi);
+	netif_tx_disable(adapter->netdev);
+	adapter->link_speed = 0;
+	netif_carrier_off(adapter->netdev);
+
+	vmxnet3_tq_cleanup(&adapter->tx_queue, adapter);
+	vmxnet3_rq_cleanup(&adapter->rx_queue, adapter);
+	vmxnet3_free_irqs(adapter);
+	return 0;
+}
+
+
+static void
+vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)
+{
+	u32 tmp;
+
+	tmp = *(u32 *)mac;
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_MACL, tmp);
+
+	tmp = (mac[5] << 8) | mac[4];
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_MACH, tmp);
+}
+
+
+static int
+vmxnet3_set_mac_addr(struct net_device *netdev, void *p)
+{
+	struct sockaddr *addr = p;
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	vmxnet3_write_mac_addr(adapter, addr->sa_data);
+
+	return 0;
+}
+
+
+/* ==================== initialization and cleanup routines ============ */
+
+static int
+vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64)
+{
+	int err;
+	unsigned long mmio_start, mmio_len;
+	struct pci_dev *pdev = adapter->pdev;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR "Failed to enable adapter %s: error %d\n",
+		       pci_name(pdev), err);
+		return err;
+	}
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
+		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
+			printk(KERN_ERR "pci_set_consistent_dma_mask failed "
+			       "for adapter %s\n", pci_name(pdev));
+			err = -EIO;
+			goto err_set_mask;
+		}
+		*dma64 = true;
+	} else {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
+			printk(KERN_ERR "pci_set_dma_mask failed for adapter "
+			       "%s\n",	pci_name(pdev));
+			err = -EIO;
+			goto err_set_mask;
+		}
+		*dma64 = false;
+	}
+
+	err = pci_request_selected_regions(pdev, (1 << 2) - 1,
+					   vmxnet3_driver_name);
+	if (err) {
+		printk(KERN_ERR "Failed to request region for adapter %s: "
+		       "error %d\n", pci_name(pdev), err);
+		goto err_set_mask;
+	}
+
+	pci_set_master(pdev);
+
+	mmio_start = pci_resource_start(pdev, 0);
+	mmio_len = pci_resource_len(pdev, 0);
+	adapter->hw_addr0 = ioremap(mmio_start, mmio_len);
+	if (!adapter->hw_addr0) {
+		printk(KERN_ERR "Failed to map bar0 for adapter %s\n",
+		       pci_name(pdev));
+		err = -EIO;
+		goto err_ioremap;
+	}
+
+	mmio_start = pci_resource_start(pdev, 1);
+	mmio_len = pci_resource_len(pdev, 1);
+	adapter->hw_addr1 = ioremap(mmio_start, mmio_len);
+	if (!adapter->hw_addr1) {
+		printk(KERN_ERR "Failed to map bar1 for adapter %s\n",
+		       pci_name(pdev));
+		err = -EIO;
+		goto err_bar1;
+	}
+	return 0;
+
+err_bar1:
+	iounmap(adapter->hw_addr0);
+err_ioremap:
+	pci_release_selected_regions(pdev, (1 << 2) - 1);
+err_set_mask:
+	pci_disable_device(pdev);
+	return err;
+}
+
+
+static void
+vmxnet3_free_pci_resources(struct vmxnet3_adapter *adapter)
+{
+	BUG_ON(!adapter->pdev);
+
+	iounmap(adapter->hw_addr0);
+	iounmap(adapter->hw_addr1);
+	pci_release_selected_regions(adapter->pdev, (1 << 2) - 1);
+	pci_disable_device(adapter->pdev);
+}
+
+
+static void
+vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
+{
+	size_t sz;
+
+	if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE -
+				    VMXNET3_MAX_ETH_HDR_SIZE) {
+		adapter->skb_buf_size = adapter->netdev->mtu +
+					VMXNET3_MAX_ETH_HDR_SIZE;
+		if (adapter->skb_buf_size < VMXNET3_MIN_T0_BUF_SIZE)
+			adapter->skb_buf_size = VMXNET3_MIN_T0_BUF_SIZE;
+
+		adapter->rx_buf_per_pkt = 1;
+	} else {
+		adapter->skb_buf_size = VMXNET3_MAX_SKB_BUF_SIZE;
+		sz = adapter->netdev->mtu - VMXNET3_MAX_SKB_BUF_SIZE +
+					    VMXNET3_MAX_ETH_HDR_SIZE;
+		adapter->rx_buf_per_pkt = 1 + (sz + PAGE_SIZE - 1) / PAGE_SIZE;
+	}
+
+	/*
+	 * for simplicity, force the ring0 size to be a multiple of
+	 * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
+	 */
+	sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN;
+	adapter->rx_queue.rx_ring[0].size = (adapter->rx_queue.rx_ring[0].size 
+
+					     sz - 1) / sz * sz;
+	adapter->rx_queue.rx_ring[0].size = min_t(u32,
+					    adapter->rx_queue.rx_ring[0].size,
+					    VMXNET3_RX_RING_MAX_SIZE / sz * 
sz);
+}
+
+
+int
+vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size,
+		      u32 rx_ring_size, u32 rx_ring2_size)
+{
+	int err;
+
+	adapter->tx_queue.tx_ring.size   = tx_ring_size;
+	adapter->tx_queue.data_ring.size = tx_ring_size;
+	adapter->tx_queue.comp_ring.size = tx_ring_size;
+	adapter->tx_queue.shared = &adapter->tqd_start->ctrl;
+	adapter->tx_queue.stopped = true;
+	err = vmxnet3_tq_create(&adapter->tx_queue, adapter);
+	if (err)
+		return err;
+
+	adapter->rx_queue.rx_ring[0].size = rx_ring_size;
+	adapter->rx_queue.rx_ring[1].size = rx_ring2_size;
+	vmxnet3_adjust_rx_ring_size(adapter);
+	adapter->rx_queue.comp_ring.size  = adapter->rx_queue.rx_ring[0].size +
+					    adapter->rx_queue.rx_ring[1].size;
+	adapter->rx_queue.qid  = 0;
+	adapter->rx_queue.qid2 = 1;
+	adapter->rx_queue.shared = &adapter->rqd_start->ctrl;
+	err = vmxnet3_rq_create(&adapter->rx_queue, adapter);
+	if (err)
+		vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+
+	return err;
+}
+
+static int
+vmxnet3_open(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter;
+	int err;
+
+	adapter = netdev_priv(netdev);
+
+	spin_lock_init(&adapter->tx_queue.tx_lock);
+
+	err = vmxnet3_create_queues(adapter, VMXNET3_DEF_TX_RING_SIZE,
+				    VMXNET3_DEF_RX_RING_SIZE,
+				    VMXNET3_DEF_RX_RING_SIZE);
+	if (err)
+		goto queue_err;
+
+	err = vmxnet3_activate_dev(adapter);
+	if (err)
+		goto activate_err;
+
+	return 0;
+
+activate_err:
+	vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+	vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+queue_err:
+	return err;
+}
+
+
+static int
+vmxnet3_close(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	/*
+	 * Reset_work may be in the middle of resetting the device, wait for 
its
+	 * completion.
+	 */
+	while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+		msleep(1);
+
+	vmxnet3_quiesce_dev(adapter);
+
+	vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+	vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+
+	clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+
+
+	return 0;
+}
+
+
+void
+vmxnet3_force_close(struct vmxnet3_adapter *adapter)
+{
+	/*
+	 * we must clear VMXNET3_STATE_BIT_RESETTING, otherwise
+	 * vmxnet3_close() will deadlock.
+	 */
+	BUG_ON(test_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state));
+
+	/* we need to enable NAPI, otherwise dev_close will deadlock */
+	napi_enable(&adapter->napi);
+	dev_close(adapter->netdev);
+}
+
+
+static int
+vmxnet3_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	int err = 0;
+
+	if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU)
+		return -EINVAL;
+
+	if (new_mtu > 1500 && !adapter->jumbo_frame)
+		return -EINVAL;
+
+	netdev->mtu = new_mtu;
+
+	/*
+	 * Reset_work may be in the middle of resetting the device, wait for 
its
+	 * completion.
+	 */
+	while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+		msleep(1);
+
+	if (netif_running(netdev)) {
+		vmxnet3_quiesce_dev(adapter);
+		vmxnet3_reset_dev(adapter);
+
+		/* we need to re-create the rx queue based on the new mtu */
+		vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+		vmxnet3_adjust_rx_ring_size(adapter);
+		adapter->rx_queue.comp_ring.size  =
+					adapter->rx_queue.rx_ring[0].size +
+					adapter->rx_queue.rx_ring[1].size;
+		err = vmxnet3_rq_create(&adapter->rx_queue, adapter);
+		if (err) {
+			printk(KERN_ERR "%s: failed to re-create rx queue,"
+				" error %d. Closing it.\n", netdev->name, err);
+			goto out;
+		}
+
+		err = vmxnet3_activate_dev(adapter);
+		if (err) {
+			printk(KERN_ERR "%s: failed to re-activate, error %d. "
+				"Closing it\n", netdev->name, err);
+			goto out;
+		}
+	}
+
+out:
+	clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+	if (err)
+		vmxnet3_force_close(adapter);
+
+	return err;
+}
+
+
+static void
+vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	netdev->features = NETIF_F_SG |
+		NETIF_F_HW_CSUM |
+		NETIF_F_HW_VLAN_TX |
+		NETIF_F_HW_VLAN_RX |
+		NETIF_F_HW_VLAN_FILTER |
+		NETIF_F_TSO |
+		NETIF_F_TSO6;
+
+	printk(KERN_INFO "features: sg csum vlan jf tso tsoIPv6");
+
+	adapter->rxcsum = true;
+	adapter->jumbo_frame = true;
+
+	if (!disable_lro) {
+		adapter->lro = true;
+		printk(" lro");
+	}
+
+	if (dma64) {
+		netdev->features |= NETIF_F_HIGHDMA;
+		printk(" highDMA");
+	}
+
+	netdev->vlan_features = netdev->features;
+	printk("\n");
+}
+
+
+static void
+vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)
+{
+	u32 tmp;
+
+	tmp = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACL);
+	*(u32 *)mac = tmp;
+
+	tmp = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACH);
+	mac[4] = tmp & 0xff;
+	mac[5] = (tmp >> 8) & 0xff;
+}
+
+
+static void
+vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
+{
+	u32 cfg;
+
+	/* intr settings */
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_GET_CONF_INTR);
+	cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+	adapter->intr.type = cfg & 0x3;
+	adapter->intr.mask_mode = (cfg >> 2) & 0x3;
+
+	if (adapter->intr.type == VMXNET3_IT_AUTO) {
+		int err;
+
+		adapter->intr.msix_entries[0].entry = 0;
+		err = pci_enable_msix(adapter->pdev, 
adapter->intr.msix_entries,
+				      VMXNET3_LINUX_MAX_MSIX_VECT);
+		if (!err) {
+			adapter->intr.num_intrs = 1;
+			adapter->intr.type = VMXNET3_IT_MSIX;
+			return;
+		}
+
+		err = pci_enable_msi(adapter->pdev);
+		if (!err) {
+			adapter->intr.num_intrs = 1;
+			adapter->intr.type = VMXNET3_IT_MSI;
+			return;
+		}
+	}
+
+	adapter->intr.type = VMXNET3_IT_INTX;
+
+	/* INT-X related setting */
+	adapter->intr.num_intrs = 1;
+}
+
+
+static void
+vmxnet3_free_intr_resources(struct vmxnet3_adapter *adapter)
+{
+	if (adapter->intr.type == VMXNET3_IT_MSIX)
+		pci_disable_msix(adapter->pdev);
+	else if (adapter->intr.type == VMXNET3_IT_MSI)
+		pci_disable_msi(adapter->pdev);
+	else
+		BUG_ON(adapter->intr.type != VMXNET3_IT_INTX);
+}
+
+
+static void
+vmxnet3_tx_timeout(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	adapter->tx_timeout_count++;
+
+	printk(KERN_ERR "%s: tx hang\n", adapter->netdev->name);
+	schedule_work(&adapter->work);
+}
+
+
+static void
+vmxnet3_reset_work(struct work_struct *data)
+{
+	struct vmxnet3_adapter *adapter;
+
+	adapter = container_of(data, struct vmxnet3_adapter, work);
+
+	/* if another thread is resetting the device, no need to proceed */
+	if (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+		return;
+
+	/* if the device is closed, we must leave it alone */
+	if (netif_running(adapter->netdev)) {
+		printk(KERN_INFO "%s: resetting\n", adapter->netdev->name);
+		vmxnet3_quiesce_dev(adapter);
+		vmxnet3_reset_dev(adapter);
+		vmxnet3_activate_dev(adapter);
+	} else {
+		printk(KERN_INFO "%s: already closed\n", 
adapter->netdev->name);
+	}
+
+	clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+}
+
+
+static int __devinit
+vmxnet3_probe_device(struct pci_dev *pdev,
+		     const struct pci_device_id *id)
+{
+	static const struct net_device_ops vmxnet3_netdev_ops = {
+		.ndo_open = vmxnet3_open,
+		.ndo_stop = vmxnet3_close,
+		.ndo_start_xmit = vmxnet3_xmit_frame,
+		.ndo_set_mac_address = vmxnet3_set_mac_addr,
+		.ndo_change_mtu = vmxnet3_change_mtu,
+		.ndo_get_stats = vmxnet3_get_stats,
+		.ndo_tx_timeout = vmxnet3_tx_timeout,
+		.ndo_set_multicast_list = vmxnet3_set_mc,
+		.ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
+		.ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
+		.ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+		.ndo_poll_controller = vmxnet3_netpoll,
+#endif
+	};
+	int err;
+	bool dma64 = false; /* stupid gcc */
+	u32 ver;
+	struct net_device *netdev;
+	struct vmxnet3_adapter *adapter;
+	u8 mac[ETH_ALEN];
+
+	netdev = alloc_etherdev(sizeof(struct vmxnet3_adapter));
+	if (!netdev) {
+		printk(KERN_ERR "Failed to alloc ethernet device for adapter "
+			"%s\n",	pci_name(pdev));
+		return -ENOMEM;
+	}
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev_priv(netdev);
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+
+	adapter->shared = pci_alloc_consistent(adapter->pdev,
+			  sizeof(struct Vmxnet3_DriverShared),
+			  &adapter->shared_pa);
+	if (!adapter->shared) {
+		printk(KERN_ERR "Failed to allocate memory for %s\n",
+			pci_name(pdev));
+		err = -ENOMEM;
+		goto err_alloc_shared;
+	}
+
+	adapter->tqd_start = pci_alloc_consistent(adapter->pdev,
+			     sizeof(struct Vmxnet3_TxQueueDesc) +
+			     sizeof(struct Vmxnet3_RxQueueDesc),
+			     &adapter->queue_desc_pa);
+
+	if (!adapter->tqd_start) {
+		printk(KERN_ERR "Failed to allocate memory for %s\n",
+			pci_name(pdev));
+		err = -ENOMEM;
+		goto err_alloc_queue_desc;
+	}
+	adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start
+							    + 1);
+
+	adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL);
+	if (adapter->pm_conf == NULL) {
+		printk(KERN_ERR "Failed to allocate memory for %s\n",
+			pci_name(pdev));
+		err = -ENOMEM;
+		goto err_alloc_pm;
+	}
+
+	err = vmxnet3_alloc_pci_resources(adapter, &dma64);
+	if (err < 0)
+		goto err_alloc_pci;
+
+	ver = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_VRRS);
+	if (ver & 1) {
+		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_VRRS, 1);
+	} else {
+		printk(KERN_ERR "Incompatible h/w version (0x%x) for adapter"
+		       " %s\n",	ver, pci_name(pdev));
+		err = -EBUSY;
+		goto err_ver;
+	}
+
+	ver = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_UVRS);
+	if (ver & 1) {
+		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_UVRS, 1);
+	} else {
+		printk(KERN_ERR "Incompatible upt version (0x%x) for "
+		       "adapter %s\n", ver, pci_name(pdev));
+		err = -EBUSY;
+		goto err_ver;
+	}
+
+	vmxnet3_declare_features(adapter, dma64);
+
+	adapter->dev_number = atomic_read(&devices_found);
+	vmxnet3_alloc_intr_resources(adapter);
+
+	vmxnet3_read_mac_addr(adapter, mac);
+	memcpy(netdev->dev_addr,  mac, netdev->addr_len);
+
+	netdev->netdev_ops = &vmxnet3_netdev_ops;
+	netdev->watchdog_timeo = 5 * HZ;
+	vmxnet3_set_ethtool_ops(netdev);
+
+	INIT_WORK(&adapter->work, vmxnet3_reset_work);
+
+	netif_napi_add(netdev, &adapter->napi, vmxnet3_poll, 64);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	err = register_netdev(netdev);
+
+	if (err) {
+		printk(KERN_ERR "Failed to register adapter %s\n",
+			pci_name(pdev));
+		goto err_register;
+	}
+
+	set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
+	atomic_inc(&devices_found);
+	return 0;
+
+err_register:
+	vmxnet3_free_intr_resources(adapter);
+err_ver:
+	vmxnet3_free_pci_resources(adapter);
+err_alloc_pci:
+	kfree(adapter->pm_conf);
+err_alloc_pm:
+	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) +
+			    sizeof(struct Vmxnet3_RxQueueDesc),
+			    adapter->tqd_start, adapter->queue_desc_pa);
+err_alloc_queue_desc:
+	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared),
+			    adapter->shared, adapter->shared_pa);
+err_alloc_shared:
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+	return err;
+}
+
+
+static void __devexit
+vmxnet3_remove_device(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	flush_scheduled_work();
+
+	unregister_netdev(netdev);
+
+	vmxnet3_free_intr_resources(adapter);
+	vmxnet3_free_pci_resources(adapter);
+	kfree(adapter->pm_conf);
+	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) +
+			    sizeof(struct Vmxnet3_RxQueueDesc),
+			    adapter->tqd_start, adapter->queue_desc_pa);
+	pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared),
+			    adapter->shared, adapter->shared_pa);
+	free_netdev(netdev);
+}
+
+
+#ifdef CONFIG_PM
+
+static int
+vmxnet3_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct Vmxnet3_PMConf *pmConf;
+	struct ethhdr *ehdr;
+	struct arphdr *ahdr;
+	u8 *arpreq;
+	struct in_device *in_dev;
+	struct in_ifaddr *ifa;
+	int i = 0;
+
+	if (!netif_running(netdev))
+		return 0;
+
+	vmxnet3_disable_all_intrs(adapter);
+	netif_device_detach(netdev);
+	netif_stop_queue(netdev);
+
+	/* Create wake-up filters. */
+	pmConf = adapter->pm_conf;
+	memset(pmConf, 0, sizeof(*pmConf));
+
+	if (adapter->wol & WAKE_UCAST) {
+		pmConf->filters[i].patternSize = ETH_ALEN;
+		pmConf->filters[i].maskSize = 1;
+		memcpy(pmConf->filters[i].pattern, netdev->dev_addr, ETH_ALEN);
+		pmConf->filters[i].mask[0] = 0x3F; /* LSB ETH_ALEN bits */
+
+		pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER;
+		i++;
+	}
+
+	if (adapter->wol & WAKE_ARP) {
+		in_dev = in_dev_get(netdev);
+		if (!in_dev)
+			goto skip_arp;
+
+		ifa = (struct in_ifaddr *)in_dev->ifa_list;
+		if (!ifa)
+			goto skip_arp;
+
+		pmConf->filters[i].patternSize = ETH_HLEN + /* Ethernet 
header*/
+			sizeof(struct arphdr) +		/* ARP header */
+			2 * ETH_ALEN +		/* 2 Ethernet addresses*/
+			2 * sizeof(u32);	/*2 IPv4 addresses */
+		pmConf->filters[i].maskSize =
+			(pmConf->filters[i].patternSize - 1) / 8 + 1;
+
+		/* ETH_P_ARP in Ethernet header. */
+		ehdr = (struct ethhdr *)pmConf->filters[i].pattern;
+		ehdr->h_proto = htons(ETH_P_ARP);
+
+		/* ARPOP_REQUEST in ARP header. */
+		ahdr = (struct arphdr *)&pmConf->filters[i].pattern[ETH_HLEN];
+		ahdr->ar_op = htons(ARPOP_REQUEST);
+		arpreq = (u8 *)(ahdr + 1);
+
+		/* The Unicast IPv4 address in 'tip' field. */
+		arpreq += 2 * ETH_ALEN + sizeof(u32);
+		*(u32 *)arpreq = ifa->ifa_address;
+
+		/* The mask for the relevant bits. */
+		pmConf->filters[i].mask[0] = 0x00;
+		pmConf->filters[i].mask[1] = 0x30; /* ETH_P_ARP */
+		pmConf->filters[i].mask[2] = 0x30; /* ARPOP_REQUEST */
+		pmConf->filters[i].mask[3] = 0x00;
+		pmConf->filters[i].mask[4] = 0xC0; /* IPv4 TIP */
+		pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */
+		in_dev_put(in_dev);
+
+		pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER;
+		i++;
+	}
+
+skip_arp:
+	if (adapter->wol & WAKE_MAGIC)
+		pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_MAGIC;
+
+	pmConf->numFilters = i;
+
+	adapter->shared->devRead.pmConfDesc.confVer = 1;
+	adapter->shared->devRead.pmConfDesc.confLen = sizeof(*pmConf);
+	adapter->shared->devRead.pmConfDesc.confPA = virt_to_phys(pmConf);
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_UPDATE_PMCFG);
+
+	pci_save_state(pdev);
+	pci_enable_wake(pdev, pci_choose_state(pdev, PMSG_SUSPEND),
+			adapter->wol);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, PMSG_SUSPEND));
+
+	return 0;
+}
+
+
+static int
+vmxnet3_resume(struct device *device)
+{
+	int err;
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	struct Vmxnet3_PMConf *pmConf;
+
+	if (!netif_running(netdev))
+		return 0;
+
+	/* Destroy wake-up filters. */
+	pmConf = adapter->pm_conf;
+	memset(pmConf, 0, sizeof(*pmConf));
+
+	adapter->shared->devRead.pmConfDesc.confVer = 1;
+	adapter->shared->devRead.pmConfDesc.confLen = sizeof(*pmConf);
+	adapter->shared->devRead.pmConfDesc.confPA = virt_to_phys(pmConf);
+
+	netif_device_attach(netdev);
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	err = pci_enable_device_mem(pdev);
+	if (err != 0)
+		return err;
+
+	pci_enable_wake(pdev, PCI_D0, 0);
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+			       VMXNET3_CMD_UPDATE_PMCFG);
+	vmxnet3_enable_all_intrs(adapter);
+
+	return 0;
+}
+
+static struct dev_pm_ops vmxnet3_pm_ops = {
+	.suspend = vmxnet3_suspend,
+	.resume = vmxnet3_resume,
+};
+#endif
+
+static struct pci_driver vmxnet3_driver = {
+	.name		= vmxnet3_driver_name,
+	.id_table	= vmxnet3_pciid_table,
+	.probe		= vmxnet3_probe_device,
+	.remove		= __devexit_p(vmxnet3_remove_device),
+#ifdef CONFIG_PM
+	.driver.pm	= &vmxnet3_pm_ops,
+#endif
+};
+
+
+static int __init
+vmxnet3_init_module(void)
+{
+	printk(KERN_INFO "%s - version %s\n", VMXNET3_DRIVER_DESC,
+		VMXNET3_DRIVER_VERSION_REPORT);
+	return pci_register_driver(&vmxnet3_driver);
+}
+
+module_init(vmxnet3_init_module);
+
+
+static void
+vmxnet3_exit_module(void)
+{
+	pci_unregister_driver(&vmxnet3_driver);
+}
+
+module_exit(vmxnet3_exit_module);
+
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_DESCRIPTION(VMXNET3_DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(VMXNET3_DRIVER_VERSION_STRING);
+
+/* This paramenter is used to control Large Receive Offload feature
+ * of the NIC. When set to non-zeora LRO is enabled.
+ */
+module_param(disable_lro, int, 0);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c 
b/drivers/net/vmxnet3/vmxnet3_ethtool.c
new file mode 100644
index 0000000..4d2b0fc
--- /dev/null
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -0,0 +1,538 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  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".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+
+#include "vmxnet3_int.h"
+
+struct vmxnet3_stat_desc {
+	char desc[ETH_GSTRING_LEN];
+	int  offset;
+};
+
+
+static u32
+vmxnet3_get_rx_csum(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	return adapter->rxcsum;
+}
+
+
+static int
+vmxnet3_set_rx_csum(struct net_device *netdev, u32 val)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	if (adapter->rxcsum != val) {
+		adapter->rxcsum = val;
+		if (netif_running(netdev)) {
+			if (val)
+				adapter->shared->devRead.misc.uptFeatures |=
+								UPT1_F_RXCSUM;
+			else
+				adapter->shared->devRead.misc.uptFeatures &=
+								~UPT1_F_RXCSUM;
+
+			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+					       VMXNET3_CMD_UPDATE_FEATURE);
+		}
+	}
+	return 0;
+}
+
+
+/* per tq stats maintained by the device */
+static const struct vmxnet3_stat_desc
+vmxnet3_tq_dev_stats[] = {
+	/* description,         offset */
+	{ "TSO pkts tx",        offsetof(struct UPT1_TxStats, TSOPktsTxOK) },
+	{ "TSO bytes tx",       offsetof(struct UPT1_TxStats, TSOBytesTxOK) },
+	{ "ucast pkts tx",      offsetof(struct UPT1_TxStats, ucastPktsTxOK) },
+	{ "ucast bytes tx",     offsetof(struct UPT1_TxStats, ucastBytesTxOK) 
},
+	{ "mcast pkts tx",      offsetof(struct UPT1_TxStats, mcastPktsTxOK) },
+	{ "mcast bytes tx",     offsetof(struct UPT1_TxStats, mcastBytesTxOK) 
},
+	{ "bcast pkts tx",      offsetof(struct UPT1_TxStats, bcastPktsTxOK) },
+	{ "bcast bytes tx",     offsetof(struct UPT1_TxStats, bcastBytesTxOK) 
},
+	{ "pkts tx err",        offsetof(struct UPT1_TxStats, pktsTxError) },
+	{ "pkts tx discard",    offsetof(struct UPT1_TxStats, pktsTxDiscard) },
+};
+
+/* per tq stats maintained by the driver */
+static const struct vmxnet3_stat_desc
+vmxnet3_tq_driver_stats[] = {
+	/* description,         offset */
+	{"drv dropped tx total", offsetof(struct vmxnet3_tq_driver_stats,
+					drop_total) },
+	{ "   too many frags",  offsetof(struct vmxnet3_tq_driver_stats,
+					drop_too_many_frags) },
+	{ "   giant hdr",       offsetof(struct vmxnet3_tq_driver_stats,
+					drop_oversized_hdr) },
+	{ "   hdr err",         offsetof(struct vmxnet3_tq_driver_stats,
+					drop_hdr_inspect_err) },
+	{ "   tso",             offsetof(struct vmxnet3_tq_driver_stats,
+					drop_tso) },
+	{ "ring full",          offsetof(struct vmxnet3_tq_driver_stats,
+					tx_ring_full) },
+	{ "pkts linearized",    offsetof(struct vmxnet3_tq_driver_stats,
+					linearized) },
+	{ "hdr cloned",         offsetof(struct vmxnet3_tq_driver_stats,
+					copy_skb_header) },
+	{ "giant hdr",          offsetof(struct vmxnet3_tq_driver_stats,
+					oversized_hdr) },
+};
+
+/* per rq stats maintained by the device */
+static const struct vmxnet3_stat_desc
+vmxnet3_rq_dev_stats[] = {
+	{ "LRO pkts rx",        offsetof(struct UPT1_RxStats, LROPktsRxOK) },
+	{ "LRO byte rx",        offsetof(struct UPT1_RxStats, LROBytesRxOK) },
+	{ "ucast pkts rx",      offsetof(struct UPT1_RxStats, ucastPktsRxOK) },
+	{ "ucast bytes rx",     offsetof(struct UPT1_RxStats, ucastBytesRxOK) 
},
+	{ "mcast pkts rx",      offsetof(struct UPT1_RxStats, mcastPktsRxOK) },
+	{ "mcast bytes rx",     offsetof(struct UPT1_RxStats, mcastBytesRxOK) 
},
+	{ "bcast pkts rx",      offsetof(struct UPT1_RxStats, bcastPktsRxOK) },
+	{ "bcast bytes rx",     offsetof(struct UPT1_RxStats, bcastBytesRxOK) 
},
+	{ "pkts rx out of buf", offsetof(struct UPT1_RxStats, pktsRxOutOfBuf) 
},
+	{ "pkts rx err",        offsetof(struct UPT1_RxStats, pktsRxError) },
+};
+
+/* per rq stats maintained by the driver */
+static const struct vmxnet3_stat_desc
+vmxnet3_rq_driver_stats[] = {
+	/* description,         offset */
+	{ "drv dropped rx total", offsetof(struct vmxnet3_rq_driver_stats,
+					   drop_total) },
+	{ "   err",            offsetof(struct vmxnet3_rq_driver_stats,
+					drop_err) },
+	{ "   fcs",            offsetof(struct vmxnet3_rq_driver_stats,
+					drop_fcs) },
+	{ "rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats,
+					rx_buf_alloc_failure) },
+};
+
+/* gloabl stats maintained by the driver */
+static const struct vmxnet3_stat_desc
+vmxnet3_global_stats[] = {
+	/* description,         offset */
+	{ "tx timeout count",   offsetof(struct vmxnet3_adapter,
+					 tx_timeout_count) }
+};
+
+
+struct net_device_stats *
+vmxnet3_get_stats(struct net_device *netdev)
+{
+	struct vmxnet3_adapter *adapter;
+	struct vmxnet3_tq_driver_stats *drvTxStats;
+	struct vmxnet3_rq_driver_stats *drvRxStats;
+	struct UPT1_TxStats *devTxStats;
+	struct UPT1_RxStats *devRxStats;
+	struct net_device_stats *net_stats = &netdev->stats;
+
+	adapter = netdev_priv(netdev);
+
+	/* Collect the dev stats into the shared area */
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, 
VMXNET3_CMD_GET_STATS);
+
+	/* Assuming that we have a single queue device */
+	devTxStats = &adapter->tqd_start->stats;
+	devRxStats = &adapter->rqd_start->stats;
+
+	/* Get access to the driver stats per queue */
+	drvTxStats = &adapter->tx_queue.stats;
+	drvRxStats = &adapter->rx_queue.stats;
+
+	memset(net_stats, 0, sizeof(*net_stats));
+
+	net_stats->rx_packets = devRxStats->ucastPktsRxOK +
+				devRxStats->mcastPktsRxOK +
+				devRxStats->bcastPktsRxOK;
+
+	net_stats->tx_packets = devTxStats->ucastPktsTxOK +
+				devTxStats->mcastPktsTxOK +
+				devTxStats->bcastPktsTxOK;
+
+	net_stats->rx_bytes = devRxStats->ucastBytesRxOK +
+			      devRxStats->mcastBytesRxOK +
+			      devRxStats->bcastBytesRxOK;
+
+	net_stats->tx_bytes = devTxStats->ucastBytesTxOK +
+			      devTxStats->mcastBytesTxOK +
+			      devTxStats->bcastBytesTxOK;
+
+	net_stats->rx_errors = devRxStats->pktsRxError;
+	net_stats->tx_errors = devTxStats->pktsTxError;
+	net_stats->rx_dropped = drvRxStats->drop_total;
+	net_stats->tx_dropped = drvTxStats->drop_total;
+	net_stats->multicast =  devRxStats->mcastPktsRxOK;
+
+	return net_stats;
+}
+
+static int
+vmxnet3_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(vmxnet3_tq_dev_stats) +
+			ARRAY_SIZE(vmxnet3_tq_driver_stats) +
+			ARRAY_SIZE(vmxnet3_rq_dev_stats) +
+			ARRAY_SIZE(vmxnet3_rq_driver_stats) +
+			ARRAY_SIZE(vmxnet3_global_stats);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int
+vmxnet3_get_regs_len(struct net_device *netdev)
+{
+	return 20 * sizeof(u32);
+}
+
+
+static void
+vmxnet3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo 
*drvinfo)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	strlcpy(drvinfo->driver, vmxnet3_driver_name, sizeof(drvinfo->driver));
+	drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
+
+	strlcpy(drvinfo->version, VMXNET3_DRIVER_VERSION_REPORT,
+		sizeof(drvinfo->version));
+	drvinfo->driver[sizeof(drvinfo->version) - 1] = '\0';
+
+	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	drvinfo->fw_version[sizeof(drvinfo->fw_version) - 1] = '\0';
+
+	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		ETHTOOL_BUSINFO_LEN);
+	drvinfo->n_stats = vmxnet3_get_sset_count(netdev, ETH_SS_STATS);
+	drvinfo->testinfo_len = 0;
+	drvinfo->eedump_len   = 0;
+	drvinfo->regdump_len  = vmxnet3_get_regs_len(netdev);
+}
+
+
+static void
+vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
+{
+	if (stringset == ETH_SS_STATS) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) {
+			memcpy(buf, vmxnet3_tq_dev_stats[i].desc,
+			       ETH_GSTRING_LEN);
+			buf += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++) {
+			memcpy(buf, vmxnet3_tq_driver_stats[i].desc,
+			       ETH_GSTRING_LEN);
+			buf += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) {
+			memcpy(buf, vmxnet3_rq_dev_stats[i].desc,
+			       ETH_GSTRING_LEN);
+			buf += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++) {
+			memcpy(buf, vmxnet3_rq_driver_stats[i].desc,
+			       ETH_GSTRING_LEN);
+			buf += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++) {
+			memcpy(buf, vmxnet3_global_stats[i].desc,
+				ETH_GSTRING_LEN);
+			buf += ETH_GSTRING_LEN;
+		}
+	}
+}
+
+
+static void
+vmxnet3_get_ethtool_stats(struct net_device *netdev,
+			  struct ethtool_stats *stats, u64  *buf)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	u8 *base;
+	int i;
+
+	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, 
VMXNET3_CMD_GET_STATS);
+
+	/* this does assume each counter is 64-bit wide */
+
+	base = (u8 *)&adapter->tqd_start->stats;
+	for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++)
+		*buf++ = *(u64 *)(base + vmxnet3_tq_dev_stats[i].offset);
+
+	base = (u8 *)&adapter->tx_queue.stats;
+	for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++)
+		*buf++ = *(u64 *)(base + vmxnet3_tq_driver_stats[i].offset);
+
+	base = (u8 *)&adapter->rqd_start->stats;
+	for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++)
+		*buf++ = *(u64 *)(base + vmxnet3_rq_dev_stats[i].offset);
+
+	base = (u8 *)&adapter->rx_queue.stats;
+	for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++)
+		*buf++ = *(u64 *)(base + vmxnet3_rq_driver_stats[i].offset);
+
+	base = (u8 *)adapter;
+	for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++)
+		*buf++ = *(u64 *)(base + vmxnet3_global_stats[i].offset);
+}
+
+
+static void
+vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void 
*p)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	u32 *buf = p;
+
+	memset(p, 0, vmxnet3_get_regs_len(netdev));
+
+	regs->version = 1;
+
+	/* Update vmxnet3_get_regs_len if we want to dump more registers */
+
+	/* make each ring use multiple of 16 bytes */
+	buf[0] = adapter->tx_queue.tx_ring.next2fill;
+	buf[1] = adapter->tx_queue.tx_ring.next2comp;
+	buf[2] = adapter->tx_queue.tx_ring.gen;
+	buf[3] = 0;
+
+	buf[4] = adapter->tx_queue.comp_ring.next2proc;
+	buf[5] = adapter->tx_queue.comp_ring.gen;
+	buf[6] = adapter->tx_queue.stopped;
+	buf[7] = 0;
+
+	buf[8] = adapter->rx_queue.rx_ring[0].next2fill;
+	buf[9] = adapter->rx_queue.rx_ring[0].next2comp;
+	buf[10] = adapter->rx_queue.rx_ring[0].gen;
+	buf[11] = 0;
+
+	buf[12] = adapter->rx_queue.rx_ring[1].next2fill;
+	buf[13] = adapter->rx_queue.rx_ring[1].next2comp;
+	buf[14] = adapter->rx_queue.rx_ring[1].gen;
+	buf[15] = 0;
+
+	buf[16] = adapter->rx_queue.comp_ring.next2proc;
+	buf[17] = adapter->rx_queue.comp_ring.gen;
+	buf[18] = 0;
+	buf[19] = 0;
+}
+
+
+static void
+vmxnet3_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_UCAST | WAKE_ARP | WAKE_MAGIC;
+	wol->wolopts = adapter->wol;
+}
+
+
+static int
+vmxnet3_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_PHY | WAKE_MCAST | WAKE_BCAST |
+			    WAKE_MAGICSECURE)) {
+		return -EOPNOTSUPP;
+	}
+
+	adapter->wol = wol->wolopts;
+
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+	return 0;
+}
+
+
+static int
+vmxnet3_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	ecmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full 
|
+			  SUPPORTED_TP;
+	ecmd->advertising = ADVERTISED_TP;
+	ecmd->port = PORT_TP;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (adapter->link_speed) {
+		ecmd->speed = adapter->link_speed;
+		ecmd->duplex = DUPLEX_FULL;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+	return 0;
+}
+
+
+static void
+vmxnet3_get_ringparam(struct net_device *netdev,
+		      struct ethtool_ringparam *param)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+	param->rx_max_pending = VMXNET3_RX_RING_MAX_SIZE;
+	param->tx_max_pending = VMXNET3_TX_RING_MAX_SIZE;
+	param->rx_mini_max_pending = 0;
+	param->rx_jumbo_max_pending = 0;
+
+	param->rx_pending = adapter->rx_queue.rx_ring[0].size;
+	param->tx_pending = adapter->tx_queue.tx_ring.size;
+	param->rx_mini_pending = 0;
+	param->rx_jumbo_pending = 0;
+}
+
+
+static int
+vmxnet3_set_ringparam(struct net_device *netdev,
+		      struct ethtool_ringparam *param)
+{
+	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+	u32 new_tx_ring_size, new_rx_ring_size;
+	u32 sz;
+	int err = 0;
+
+	if (param->tx_pending == 0 || param->tx_pending >
+						VMXNET3_TX_RING_MAX_SIZE)
+		return -EINVAL;
+
+	if (param->rx_pending == 0 || param->rx_pending >
+						VMXNET3_RX_RING_MAX_SIZE)
+		return -EINVAL;
+
+
+	/* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */
+	new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) &
+ 
~VMXNET3_RING_SIZE_MASK;
+	new_tx_ring_size = min_t(u32, new_tx_ring_size,
+				 VMXNET3_TX_RING_MAX_SIZE);
+	if (new_tx_ring_size > VMXNET3_TX_RING_MAX_SIZE || (new_tx_ring_size %
+						VMXNET3_RING_SIZE_ALIGN) != 0)
+		return -EINVAL;
+
+	/* ring0 has to be a multiple of
+	 * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
+	 */
+	sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN;
+	new_rx_ring_size = (param->rx_pending + sz - 1) / sz * sz;
+	new_rx_ring_size = min_t(u32, new_rx_ring_size,
+				 VMXNET3_RX_RING_MAX_SIZE / sz * sz);
+	if (new_rx_ring_size > VMXNET3_RX_RING_MAX_SIZE || (new_rx_ring_size %
+							   sz) != 0)
+		return -EINVAL;
+
+	if (new_tx_ring_size == adapter->tx_queue.tx_ring.size &&
+			new_rx_ring_size == adapter->rx_queue.rx_ring[0].size) 
{
+		return 0;
+	}
+
+	/*
+	 * Reset_work may be in the middle of resetting the device, wait for 
its
+	 * completion.
+	 */
+	while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+		msleep(1);
+
+	if (netif_running(netdev)) {
+		vmxnet3_quiesce_dev(adapter);
+		vmxnet3_reset_dev(adapter);
+
+		/* recreate the rx queue and the tx queue based on the
+		 * new sizes */
+		vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+		vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+
+		err = vmxnet3_create_queues(adapter, new_tx_ring_size,
+			new_rx_ring_size, VMXNET3_DEF_RX_RING_SIZE);
+		if (err) {
+			/* failed, most likely because of OOM, try default
+			 * size */
+			printk(KERN_ERR "%s: failed to apply new sizes, try 
the"
+				" default ones\n", netdev->name);
+			err = vmxnet3_create_queues(adapter,
+						    VMXNET3_DEF_TX_RING_SIZE,
+						    VMXNET3_DEF_RX_RING_SIZE,
+						    VMXNET3_DEF_RX_RING_SIZE);
+			if (err) {
+				printk(KERN_ERR "%s: failed to create queues "
+					"with default sizes. Closing it\n",
+					netdev->name);
+				goto out;
+			}
+		}
+
+		err = vmxnet3_activate_dev(adapter);
+		if (err)
+			printk(KERN_ERR "%s: failed to re-activate, error %d."
+				" Closing it\n", netdev->name, err);
+	}
+
+out:
+	clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+	if (err)
+		vmxnet3_force_close(adapter);
+
+	return err;
+}
+
+
+static struct ethtool_ops vmxnet3_ethtool_ops = {
+	.get_settings      = vmxnet3_get_settings,
+	.get_drvinfo       = vmxnet3_get_drvinfo,
+	.get_regs_len      = vmxnet3_get_regs_len,
+	.get_regs          = vmxnet3_get_regs,
+	.get_wol           = vmxnet3_get_wol,
+	.set_wol           = vmxnet3_set_wol,
+	.get_link          = ethtool_op_get_link,
+	.get_rx_csum       = vmxnet3_get_rx_csum,
+	.set_rx_csum       = vmxnet3_set_rx_csum,
+	.get_tx_csum       = ethtool_op_get_tx_csum,
+	.set_tx_csum       = ethtool_op_set_tx_hw_csum,
+	.get_sg            = ethtool_op_get_sg,
+	.set_sg            = ethtool_op_set_sg,
+	.get_tso           = ethtool_op_get_tso,
+	.set_tso           = ethtool_op_set_tso,
+	.get_strings       = vmxnet3_get_strings,
+	.get_sset_count	   = vmxnet3_get_sset_count,
+	.get_ethtool_stats = vmxnet3_get_ethtool_stats,
+	.get_ringparam     = vmxnet3_get_ringparam,
+	.set_ringparam     = vmxnet3_set_ringparam,
+};
+
+void vmxnet3_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
+}
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h 
b/drivers/net/vmxnet3/vmxnet3_int.h
new file mode 100644
index 0000000..cf4b08d
--- /dev/null
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -0,0 +1,389 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  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".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#ifndef _VMXNET3_INT_H
+#define _VMXNET3_INT_H
+
+#include <linux/types.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/uaccess.h>
+#include <asm/dma.h>
+#include <asm/page.h>
+
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/in.h>
+#include <linux/etherdevice.h>
+#include <asm/checksum.h>
+#include <linux/if_vlan.h>
+#include <linux/if_arp.h>
+#include <linux/inetdevice.h>
+#include <linux/dst.h>
+
+#include "vmxnet3_defs.h"
+
+#ifdef DEBUG
+# define VMXNET3_DRIVER_VERSION_REPORT 
VMXNET3_DRIVER_VERSION_STRING"-NAPI(debug)"
+#else
+# define VMXNET3_DRIVER_VERSION_REPORT VMXNET3_DRIVER_VERSION_STRING"-NAPI"
+#endif
+
+
+/*
+ * Version numbers
+ */
+#define VMXNET3_DRIVER_VERSION_STRING   "1.0.4.0-k"
+
+/* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
+#define VMXNET3_DRIVER_VERSION_NUM      0x01000400
+
+
+/*
+ * Capabilities
+ */
+
+enum {
+	VMNET_CAP_SG	        = 0x0001, /* Can do scatter-gather transmits. 
*/
+	VMNET_CAP_IP4_CSUM      = 0x0002, /* Can checksum only TCP/UDP over
+					   * IPv4 */
+	VMNET_CAP_HW_CSUM       = 0x0004, /* Can checksum all packets. */
+	VMNET_CAP_HIGH_DMA      = 0x0008, /* Can DMA to high memory. */
+	VMNET_CAP_TOE	        = 0x0010, /* Supports TCP/IP offload. */
+	VMNET_CAP_TSO	        = 0x0020, /* Supports TCP Segmentation
+					   * offload */
+	VMNET_CAP_SW_TSO        = 0x0040, /* Supports SW TCP Segmentation */
+	VMNET_CAP_VMXNET_APROM  = 0x0080, /* Vmxnet APROM support */
+	VMNET_CAP_HW_TX_VLAN    = 0x0100, /* Can we do VLAN tagging in HW */
+	VMNET_CAP_HW_RX_VLAN    = 0x0200, /* Can we do VLAN untagging in HW */
+	VMNET_CAP_SW_VLAN       = 0x0400, /* VLAN tagging/untagging in SW */
+	VMNET_CAP_WAKE_PCKT_RCV = 0x0800, /* Can wake on network packet recv? 
*/
+	VMNET_CAP_ENABLE_INT_INLINE = 0x1000,  /* Enable Interrupt Inline */
+	VMNET_CAP_ENABLE_HEADER_COPY = 0x2000,  /* copy header for vmkernel */
+	VMNET_CAP_TX_CHAIN      = 0x4000, /* Guest can use multiple tx entries
+					  * for a pkt */
+	VMNET_CAP_RX_CHAIN      = 0x8000, /* pkt can span multiple rx entries 
*/
+	VMNET_CAP_LPD           = 0x10000, /* large pkt delivery */
+	VMNET_CAP_BPF           = 0x20000, /* BPF Support in VMXNET Virtual 
HW*/
+	VMNET_CAP_SG_SPAN_PAGES = 0x40000, /* Scatter-gather can span 
multiple*/
+					   /* pages transmits */
+	VMNET_CAP_IP6_CSUM      = 0x80000, /* Can do IPv6 csum offload. */
+	VMNET_CAP_TSO6         = 0x100000, /* TSO seg. offload for IPv6 pkts. 
*/
+	VMNET_CAP_TSO256k      = 0x200000, /* Can do TSO seg offload for */
+					   /* pkts up to 256kB. */
+	VMNET_CAP_UPT          = 0x400000  /* Support UPT */
+};
+
+/*
+ * PCI vendor and device IDs.
+ */
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMXNET3    0x07B0
+#define MAX_ETHERNET_CARDS		10
+#define MAX_PCI_PASSTHRU_DEVICE		6
+
+struct vmxnet3_cmd_ring {
+	union Vmxnet3_GenericDesc *base;
+	u32		size;
+	u32		next2fill;
+	u32		next2comp;
+	u8		gen;
+	dma_addr_t	basePA;
+};
+
+static inline void
+vmxnet3_cmd_ring_adv_next2fill(struct vmxnet3_cmd_ring *ring)
+{
+	ring->next2fill++;
+	if (unlikely(ring->next2fill == ring->size)) {
+		ring->next2fill = 0;
+		VMXNET3_FLIP_RING_GEN(ring->gen);
+	}
+}
+
+static inline void
+vmxnet3_cmd_ring_adv_next2comp(struct vmxnet3_cmd_ring *ring)
+{
+	VMXNET3_INC_RING_IDX_ONLY(ring->next2comp, ring->size);
+}
+
+static inline int
+vmxnet3_cmd_ring_desc_avail(struct vmxnet3_cmd_ring *ring)
+{
+	return (ring->next2comp > ring->next2fill ? 0 : ring->size) +
+		ring->next2comp - ring->next2fill - 1;
+}
+
+struct vmxnet3_comp_ring {
+	union Vmxnet3_GenericDesc *base;
+	u32               size;
+	u32               next2proc;
+	u8                gen;
+	u8                intr_idx;
+	dma_addr_t           basePA;
+};
+
+static inline void
+vmxnet3_comp_ring_adv_next2proc(struct vmxnet3_comp_ring *ring)
+{
+	ring->next2proc++;
+	if (unlikely(ring->next2proc == ring->size)) {
+		ring->next2proc = 0;
+		VMXNET3_FLIP_RING_GEN(ring->gen);
+	}
+}
+
+struct vmxnet3_tx_data_ring {
+	struct Vmxnet3_TxDataDesc *base;
+	u32              size;
+	dma_addr_t          basePA;
+};
+
+enum vmxnet3_buf_map_type {
+	VMXNET3_MAP_INVALID = 0,
+	VMXNET3_MAP_NONE,
+	VMXNET3_MAP_SINGLE,
+	VMXNET3_MAP_PAGE,
+};
+
+struct vmxnet3_tx_buf_info {
+	u32      map_type;
+	u16      len;
+	u16      sop_idx;
+	dma_addr_t  dma_addr;
+	struct sk_buff *skb;
+};
+
+struct vmxnet3_tq_driver_stats {
+	u64 drop_total;     /* # of pkts dropped by the driver, the
+				* counters below track droppings due to
+				* different reasons
+				*/
+	u64 drop_too_many_frags;
+	u64 drop_oversized_hdr;
+	u64 drop_hdr_inspect_err;
+	u64 drop_tso;
+
+	u64 tx_ring_full;
+	u64 linearized;         /* # of pkts linearized */
+	u64 copy_skb_header;    /* # of times we have to copy skb header */
+	u64 oversized_hdr;
+};
+
+struct vmxnet3_tx_ctx {
+	bool   ipv4;
+	u16 mss;
+	u32 eth_ip_hdr_size; /* only valid for pkts requesting tso or csum
+				 * offloading
+				 */
+	u32 l4_hdr_size;     /* only valid if mss != 0 */
+	u32 copy_size;       /* # of bytes copied into the data ring */
+	union Vmxnet3_GenericDesc *sop_txd;
+	union Vmxnet3_GenericDesc *eop_txd;
+};
+
+struct vmxnet3_tx_queue {
+	spinlock_t                      tx_lock;
+	struct vmxnet3_cmd_ring         tx_ring;
+	struct vmxnet3_tx_buf_info     *buf_info;
+	struct vmxnet3_tx_data_ring     data_ring;
+	struct vmxnet3_comp_ring        comp_ring;
+	struct Vmxnet3_TxQueueCtrl            *shared;
+	struct vmxnet3_tq_driver_stats  stats;
+	bool                            stopped;
+	int                             num_stop;  /* # of times the queue is
+						    * stopped */
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+enum vmxnet3_rx_buf_type {
+	VMXNET3_RX_BUF_NONE = 0,
+	VMXNET3_RX_BUF_SKB = 1,
+	VMXNET3_RX_BUF_PAGE = 2
+};
+
+struct vmxnet3_rx_buf_info {
+	enum vmxnet3_rx_buf_type buf_type;
+	u16     len;
+	union {
+		struct sk_buff *skb;
+		struct page    *page;
+	};
+	dma_addr_t dma_addr;
+};
+
+struct vmxnet3_rx_ctx {
+	struct sk_buff *skb;
+	u32 sop_idx;
+};
+
+struct vmxnet3_rq_driver_stats {
+	u64 drop_total;
+	u64 drop_err;
+	u64 drop_fcs;
+	u64 rx_buf_alloc_failure;
+};
+
+struct vmxnet3_rx_queue {
+	struct vmxnet3_cmd_ring   rx_ring[2];
+	struct vmxnet3_comp_ring  comp_ring;
+	struct vmxnet3_rx_ctx     rx_ctx;
+	u32 qid;            /* rqID in RCD for buffer from 1st ring */
+	u32 qid2;           /* rqID in RCD for buffer from 2nd ring */
+	u32 uncommitted[2]; /* # of buffers allocated since last RXPROD
+				* update */
+	struct vmxnet3_rx_buf_info     *buf_info[2];
+	struct Vmxnet3_RxQueueCtrl            *shared;
+	struct vmxnet3_rq_driver_stats  stats;
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+#define VMXNET3_LINUX_MAX_MSIX_VECT     1
+
+struct vmxnet3_intr {
+	enum vmxnet3_intr_mask_mode  mask_mode;
+	enum vmxnet3_intr_type       type;	/* MSI-X, MSI, or INTx? */
+	u8  num_intrs;			/* # of intr vectors */
+	u8  event_intr_idx;		/* idx of the intr vector for event */
+	u8  mod_levels[VMXNET3_LINUX_MAX_MSIX_VECT]; /* moderation level */
+#ifdef CONFIG_PCI_MSI
+	struct msix_entry msix_entries[VMXNET3_LINUX_MAX_MSIX_VECT];
+#endif
+};
+
+#define VMXNET3_STATE_BIT_RESETTING   0
+#define VMXNET3_STATE_BIT_QUIESCED    1
+struct vmxnet3_adapter {
+	struct vmxnet3_tx_queue         tx_queue;
+	struct vmxnet3_rx_queue         rx_queue;
+	struct napi_struct              napi;
+	struct vlan_group              *vlan_grp;
+
+	struct vmxnet3_intr             intr;
+
+	struct Vmxnet3_DriverShared    *shared;
+	struct Vmxnet3_PMConf          *pm_conf;
+	struct Vmxnet3_TxQueueDesc     *tqd_start;     /* first tx queue desc 
*/
+	struct Vmxnet3_RxQueueDesc     *rqd_start;     /* first rx queue desc 
*/
+	struct net_device              *netdev;
+	struct pci_dev                 *pdev;
+
+	u8				*hw_addr0; /* for BAR 0 */
+	u8				*hw_addr1; /* for BAR 1 */
+
+	/* feature control */
+	bool				rxcsum;
+	bool				lro;
+	bool				jumbo_frame;
+
+	/* rx buffer related */
+	unsigned			skb_buf_size;
+	int		rx_buf_per_pkt;  /* only apply to the 1st ring */
+	dma_addr_t			shared_pa;
+	dma_addr_t queue_desc_pa;
+
+	/* Wake-on-LAN */
+	u32     wol;
+
+	/* Link speed */
+	u32     link_speed; /* in mbps */
+
+	u64     tx_timeout_count;
+	struct work_struct work;
+
+	unsigned long  state;    /* VMXNET3_STATE_BIT_xxx */
+
+	int dev_number;
+};
+
+#define VMXNET3_WRITE_BAR0_REG(adapter, reg, val)  \
+	writel((val), (adapter)->hw_addr0 + (reg))
+#define VMXNET3_READ_BAR0_REG(adapter, reg)        \
+	readl((adapter)->hw_addr0 + (reg))
+
+#define VMXNET3_WRITE_BAR1_REG(adapter, reg, val)  \
+	writel((val), (adapter)->hw_addr1 + (reg))
+#define VMXNET3_READ_BAR1_REG(adapter, reg)        \
+	readl((adapter)->hw_addr1 + (reg))
+
+#define VMXNET3_WAKE_QUEUE_THRESHOLD(tq)  (5)
+#define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \
+	((rq)->rx_ring[ring_idx].size >> 3)
+
+#define VMXNET3_GET_ADDR_LO(dma)   ((u32)(dma))
+#define VMXNET3_GET_ADDR_HI(dma)   ((u32)(((u64)(dma)) >> 32))
+
+/* must be a multiple of VMXNET3_RING_SIZE_ALIGN */
+#define VMXNET3_DEF_TX_RING_SIZE    512
+#define VMXNET3_DEF_RX_RING_SIZE    256
+
+#define VMXNET3_MAX_ETH_HDR_SIZE    22
+#define VMXNET3_MAX_SKB_BUF_SIZE    (3*1024)
+
+int
+vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
+
+int
+vmxnet3_activate_dev(struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_force_close(struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_reset_dev(struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq,
+		   struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq,
+		   struct vmxnet3_adapter *adapter);
+
+int
+vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
+		      u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
+
+extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
+extern struct net_device_stats *vmxnet3_get_stats(struct net_device *netdev);
+
+extern char vmxnet3_driver_name[];
+#endif

^ permalink raw reply related

* Re: N_PPP_SYNC ldisc BUG: sleeping function called from invalid context
From: Jarek Poplawski @ 2009-09-30 21:12 UTC (permalink / raw)
  To: Tilman Schmidt; +Cc: Alan Cox, linux-kernel, netdev, Alan Cox
In-Reply-To: <4AC3A986.4080808@imap.cc>

Tilman Schmidt wrote, On 09/30/2009 08:55 PM:

> Alan Cox schrieb:
>>>  [<c026d39b>] tty_unthrottle+0x10/0x38
>>>  [<f8dcc31f>] ppp_sync_receive+0x168/0x170 [ppp_synctty]
>>>  [<f8fbb9ce>] handle_minor_recv+0x187/0x1cd [capi]
>>>  [<f8fbc19b>] capi_recv_message+0x1d9/0x24e [capi]
>> Really need to see the rest of the call trace to be sure
> 
> There wasn't more than what I posted. I had six of them, they looked all
> identical, and all of them ended after the kernel_thread_helper line. 
> 
>>> Turns out the ppp_sync_receive() function (drivers/net/ppp_synctty.c
>>> line 385ff.) has a comment in front stating:
>>>
>>> /*
>>>  * This can now be called from hard interrupt level as well
>>>  * as soft interrupt level or mainline.
>>>  */
>> Which is wrong. The flip_buffer_push -> rx processing path should never
>> be called from IRQ context and that was fixed for various drivers that
>> mis-set tty->low_latency, as well as in the PPP rework. The PPP case is
>> actually unrelated in many was.
> 
> Might be worth correcting that text then before is misleads someone.
> 
>>> Opinions?
>> See how we got into that code direct from an IRQ path. The expectation of
>> the tty logic is that it gets processed from work queues either
>> specifically in driver or via tty_flip_buffer_push when tty->low_latency
>> = 0
> 
> I'm at a loss here. According to all the backtraces:
> 
> - ppp_sync_receive() was called, as the LD's receive_buf method,
>   via handle_recv_skb() [drivers/isdn/capi/capi.c line 504, inlined]
>   from handle_minor_recv() [drivers/isdn/capi/capi.c line 519]
> 
> - handle_minor_recv() was called from capi_recv_message()
>   [drivers/isdn/capi/capi.c line 656]
> 
> - capi_recv_message() was called, as the CAPI application's
>   recv_message method, from recv_handler()
>   [drivers/isdn/capi/kcapi.c line 268]
> 
> - recv_handler() is never called directly. It's only scheduled
>   via the work queue ap->recv_work from capi_ctr_handle_message()
>   [drivers/isdn/capi/kcapi.c line 349]
> 
> Even if we don't trust the backtraces, there's not much room for
> another activation path. So for all I know, the expectation of the
> tty logic should have been met. The call was indeed processed from
> a work queue.
> 
> Why then does mutex_lock() complain?
 

Hmm... capi_recv_message() calls handle_minor_recv() under
spin_lock_irqsave(), doesn't it?

Jarek P.

^ permalink raw reply


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