Netdev List
 help / color / mirror / Atom feed
* Re: Net driver module dependencies on PHY driver modules
From: Tim Gardner @ 2009-10-31 15:34 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: Matt Carlson, Michael Chan, netdev, 553024
In-Reply-To: <1256989326.3136.284.camel@localhost>

Ben Hutchings wrote:
> I'm handling a bug report <http://bugs.debian.org/553024> relating to
> tg3 using phylib and missing the broadcom module.
> 
> There seem to be two general problems here:
> 1. PHY drivers are not auto-loaded
> 2. An initramfs builder cannot statically determine that a net device
> requires a PHY driver
> 
> It seems to me that PHY drivers should have aliases based on MDIO PHY
> ids, and phylib should request_module() if no suitable driver is
> registered.  This would solve (1) and go some way to solving (2).
> 
> Ben.
> 

I encountered the same issue with Karmic and worked around it by
building in all of the phylib modules, e.g., CONFIG_BROADCOM_PHY=y. I
agree that its not the best long term solution.

rtg
-- 
Tim Gardner tim.gardner@canonical.com

^ permalink raw reply

* Re: RFC: netdev: allow ethtool physical id to drop rtnl_lock
From: Michael Chan @ 2009-10-31 16:44 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev@vger.kernel.org
In-Reply-To: <20091030104201.6bb03b23@nehalam>


On Fri, 2009-10-30 at 10:42 -0700, Stephen Hemminger wrote:
> The ethtool operation to blink LED can take an indeterminately long time,
> blocking out other operations (via rtnl_lock). This patch is an attempt
> to work around the problem.
> 
> It does need more discussion, because it will mean that drivers that formerly
> were protected from changes during blink aren't.  For example, user could
> start device blinking, and then plug in cable causing change netlink event
> to change state or pull cable and have device come down.

Yeah, the biggest concern is shutting down the device while it is still
blinking.  During shutdown, some devices are brought to low power state
and the chip will no longer respond to I/Os to blink the LEDs.  On some
systems, this can cause bus hang or NMI.

> 
> The other possibility is to do this on a driver by driver basis
> which is more effort.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> 
> --- a/net/core/ethtool.c	2009-10-30 10:27:23.621917624 -0700
> +++ b/net/core/ethtool.c	2009-10-30 10:35:53.787670774 -0700
> @@ -17,6 +17,7 @@
>  #include <linux/errno.h>
>  #include <linux/ethtool.h>
>  #include <linux/netdevice.h>
> +#include <linux/rtnetlink.h>
>  #include <asm/uaccess.h>
>  
>  /*
> @@ -781,6 +782,8 @@ static int ethtool_get_strings(struct ne
>  static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
>  {
>  	struct ethtool_value id;
> +	int err;
> +	static int busy;
>  
>  	if (!dev->ethtool_ops->phys_id)
>  		return -EOPNOTSUPP;
> @@ -788,7 +791,21 @@ static int ethtool_phys_id(struct net_de
>  	if (copy_from_user(&id, useraddr, sizeof(id)))
>  		return -EFAULT;
>  
> -	return dev->ethtool_ops->phys_id(dev, id.data);
> +	if (busy)
> +		return -EBUSY;
> +
> +	/* This operation may take a long time, drop lock */
> +	busy = 1;
> +	dev_hold(dev);
> +	rtnl_unlock();
> +
> +	err = dev->ethtool_ops->phys_id(dev, id.data);
> +
> +	rtnl_lock();
> +	dev_put(dev);
> +	busy = 0;
> +
> +	return err;
>  }
>  
>  static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



^ permalink raw reply

* Re: [RFC] multiqueue changes
From: Michael Chan @ 2009-10-31 17:25 UTC (permalink / raw)
  To: Jarek Poplawski
  Cc: Patrick McHardy, Eric Dumazet, David S. Miller, Linux Netdev List
In-Reply-To: <20091030100033.GA6150@ff.dom.local>


On Fri, 2009-10-30 at 03:00 -0700, Jarek Poplawski wrote:
> On Thu, Oct 29, 2009 at 11:12:39PM +0100, Patrick McHardy wrote:
> > Jarek Poplawski wrote:
> > > On Thu, Oct 29, 2009 at 05:37:23PM +0100, Patrick McHardy wrote:
> > > ...
> > >> Well, we do need both values for supporting changes to the actually
> > >> used numbers of TX queues. If I understood Dave's explanation correctly,
> > >> this is also what's intended. It also doesn't seem unreasonable
> > >> what bnx2 is doing.
> > > 
> > > Exactly. With a growing number of cores, both available and powered
> > > off, these values will be soon treated more carefully than now.
> > > 
> > >> But getting back to the problem Eric reported - so you're suggesting
> > >> that bnx2.c should also adjust num_tx_queues in case the hardware
> > >> doesn't support multiqueue? That seems reasonable as well.
> > > 
> > > Currently, declaring num_tx_queues with alloc_netdev_mq() looks like
> > > too soon for some drivers. It seems they should be able to do it
> > > separately later during the .probe.
> > 
> > The value passed into alloc_netdev_mq() is just used for allocation
> > purposes, from what I can tell there's no downside in reducing it
> > before the dev_activate() call.
> 
> Right, but IMHO this reducing (or reallocation) should be done with
> some API. Simple overwriting of num_tx_queues proposed by Eric, even
> if no downside now, seems to be asking for problems in the future.
> 
> > > There is a question if .ndo_open should be considered too.
> > 
> > I currently can't see any purpose in decreasing num_tx_queues after
> > registration instead of real_num_tx_queues.
> 
> I agree, but since Eric's example shows some drivers do it (almost)
> like this, I'd prefer authors/maintainers answer this question.
> 

We need the netdev and the private structure at the beginning of
->probe() to store values as we probe the device.  Later on in
->probe(), we'll know whether the device supports MSI-X and multiqueue.
If we successfully enable MSI-X in ->ndo_open(), tx multiqueue will be
used.

So if we can separate the allocation of the netdev and the private
structure from the tx queues, we can allocate and set the exact number
of num_tx_queues in ->ndo_open().



^ permalink raw reply

* Re: [PATCH] e1000: the power down when running ifdown command
From: Stephen Hemminger @ 2009-10-31 17:58 UTC (permalink / raw)
  To: Naohiro Ooiwa
  Cc: e1000-devel, netdev, jesse.brandeburg, john.ronciak,
	jeffrey.t.kirsher, Andrew Morton, svaidy, davem
In-Reply-To: <4AEC05E8.40600@miraclelinux.com>

On Sat, 31 Oct 2009 18:39:52 +0900
Naohiro Ooiwa <nooiwa@miraclelinux.com> wrote:

> Hi All
> 
> I resend my patch.
> Sorry, my previous mail lacked an explanation.
> 
> 
> The e1000 driver doesn't let the power down when running ifdown command.
> So, I set to the D3hot state of a PCI device at the end of e1000_close().
> 
> With this modification, e1000 driver reduces power by ifdown.
> It's about 6 watts when I measured a total power of one server machine
> in my environment.
> 
> I tested this patch. The result is good enough to me.
> 
> Could you please check my patch ?
> If I should have other considerations, please tell me.
> 


Does this work with Wake On Lan? 

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference

^ permalink raw reply

* Re: large packet loss take2 2.6.31.x
From: Frans Pop @ 2009-10-31 18:44 UTC (permalink / raw)
  To: Caleb Cushing; +Cc: linux-kernel, netdev
In-Reply-To: <81bfc67a0910310721p21046931o9b512cfd0a8a7acb@mail.gmail.com>

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

Adding netdev in CC. Original message + attachments follow.

=========
so ever since arch rolled out 2.6.31.x I've been having problems with
my network (again) where I've been losing a large amount of packets
(just testing with mtr somewhere between 30/50%). first I figured it
was the same problem as I had in 2.6.30.x (and maybe it is?) but that
appeared to get fixed. when I started bisecting the bug wasn't
apparent in 2.6.31.0 but I knew for sure it was in .5 (I couldn't
remember if I had noticed it again in .3)

I'm attaching the bisection log and a 'good' dmesg output.

c9fb3ded7a8a6769f3bcb3ef3d9aed61d3e376a9 is the first bad commit

I'm not going to pretend to understand why this patch is breaking my
networking but between bisection and testing it appears to be... I've
never bisected before and I'm definitely not a kernel hacker (I can
barely read C).

I should also note that the wireshark dump here
http://bugzilla.kernel.org/show_bug.cgi?id=13835 is related to this.
and if it's not the same bug then possibly a new one should be opened.

P.S. I'm not subscribed to the list please CC me

Caleb Cushing
http://xenoterracide.blogspot.com


[-- Attachment #2: bisect.log --]
[-- Type: text/x-log, Size: 1347 bytes --]

# bad: [e2984cbfddd5c8fac88b24d7e5f28e1cfb6f3838] Linux 2.6.31.5
# good: [74fca6a42863ffacaf7ba6f1936a9f228950f657] Linux 2.6.31
git bisect start 'v2.6.31.5' 'v2.6.31' '--'
# good: [08f30ff9811e59c08d1cee043ce55b2e862efe58] tty: USB hangup is racy
git bisect good 08f30ff9811e59c08d1cee043ce55b2e862efe58
# bad: [ddf2acb72f3df470ce15eb23ee97cd3be23016f8] KVM: fix LAPIC timer period overflow
git bisect bad ddf2acb72f3df470ce15eb23ee97cd3be23016f8
# bad: [03429ffaea91375d8ed80a60fa13c9ffe694539a] Fix idle time field in /proc/uptime
git bisect bad 03429ffaea91375d8ed80a60fa13c9ffe694539a
# bad: [2f670d465897b491da0b82fd8b047b9ec75bf8c8] USB: xhci: Support full speed devices.
git bisect bad 2f670d465897b491da0b82fd8b047b9ec75bf8c8
# bad: [b8580fde3ba44a0f00bf186dc5e4935bbd51be29] usb-serial: fix termios initialization logic
git bisect bad b8580fde3ba44a0f00bf186dc5e4935bbd51be29
# bad: [c9fb3ded7a8a6769f3bcb3ef3d9aed61d3e376a9] usb-serial: change referencing of port and serial structures
git bisect bad c9fb3ded7a8a6769f3bcb3ef3d9aed61d3e376a9
# good: [fa31221e38207cece07a6d96854a0fcf47c75ae5] hwmon: (asus_atk0110) Add maintainer information
git bisect good fa31221e38207cece07a6d96854a0fcf47c75ae5
# good: [17fd426331d1e4611654985dd545a52d200dd9d1] tty: USB serial termios bits
git bisect good 17fd426331d1e4611654985dd545a52d200dd9d1

[-- Attachment #3: dmesg.log --]
[-- Type: text/x-log, Size: 31964 bytes --]

Linux version 2.6.31.1-test-00092-g17fd426 (xenoterracide@slave4) (gcc version 4.4.2 (GCC) ) #15 SMP PREEMPT Sat Oct 31 09:54:39 EDT 2009
Command line: root=/dev/disk/by-uuid/e9367b57-da02-48bf-9cd7-d41ce53520a3 ro
KERNEL supported cpus:
  Intel GenuineIntel
  AMD AuthenticAMD
  Centaur CentaurHauls
BIOS-provided physical RAM map:
 BIOS-e820: 0000000000000000 - 0000000000099c00 (usable)
 BIOS-e820: 0000000000099c00 - 00000000000a0000 (reserved)
 BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved)
 BIOS-e820: 0000000000100000 - 00000000cf590000 (usable)
 BIOS-e820: 00000000cf590000 - 00000000cf5e3000 (ACPI NVS)
 BIOS-e820: 00000000cf5e3000 - 00000000cf5f0000 (ACPI data)
 BIOS-e820: 00000000cf5f0000 - 00000000cf600000 (reserved)
 BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved)
 BIOS-e820: 00000000fec00000 - 0000000100000000 (reserved)
 BIOS-e820: 0000000100000000 - 00000001b0000000 (usable)
DMI 2.5 present.
last_pfn = 0x1b0000 max_arch_pfn = 0x400000000
MTRR default type: uncachable
MTRR fixed ranges enabled:
  00000-9FFFF write-back
  A0000-BFFFF uncachable
  C0000-E7FFF write-protect
  E8000-EFFFF uncachable
  F0000-FFFFF write-through
MTRR variable ranges enabled:
  0 base 100000000 mask F80000000 write-back
  1 base 180000000 mask FE0000000 write-back
  2 base 1A0000000 mask FF0000000 write-back
  3 base 000000000 mask F80000000 write-back
  4 base 080000000 mask FC0000000 write-back
  5 base 0C0000000 mask FF0000000 write-back
  6 base 0CF700000 mask FFFF00000 uncachable
  7 base 0CF800000 mask FFF800000 uncachable
x86 PAT enabled: cpu 0, old 0x7040600070406, new 0x7010600070106
e820 update range: 00000000cf700000 - 0000000100000000 (usable) ==> (reserved)
last_pfn = 0xcf590 max_arch_pfn = 0x400000000
e820 update range: 0000000000001000 - 0000000000006000 (usable) ==> (reserved)
Scanning 1 areas for low memory corruption
modified physical RAM map:
 modified: 0000000000000000 - 0000000000001000 (usable)
 modified: 0000000000001000 - 0000000000006000 (reserved)
 modified: 0000000000006000 - 0000000000099c00 (usable)
 modified: 0000000000099c00 - 00000000000a0000 (reserved)
 modified: 00000000000f0000 - 0000000000100000 (reserved)
 modified: 0000000000100000 - 00000000cf590000 (usable)
 modified: 00000000cf590000 - 00000000cf5e3000 (ACPI NVS)
 modified: 00000000cf5e3000 - 00000000cf5f0000 (ACPI data)
 modified: 00000000cf5f0000 - 00000000cf600000 (reserved)
 modified: 00000000e0000000 - 00000000f0000000 (reserved)
 modified: 00000000fec00000 - 0000000100000000 (reserved)
 modified: 0000000100000000 - 00000001b0000000 (usable)
initial memory mapped : 0 - 20000000
init_memory_mapping: 0000000000000000-00000000cf590000
 0000000000 - 00cf400000 page 2M
 00cf400000 - 00cf590000 page 4k
kernel direct mapping tables up to cf590000 @ 8000-e000
init_memory_mapping: 0000000100000000-00000001b0000000
 0100000000 - 01b0000000 page 2M
kernel direct mapping tables up to 1b0000000 @ c000-14000
RAMDISK: 37ef1000 - 37fef9a7
ACPI: RSDP 00000000000f97a0 00024 (v02 DELL  )
ACPI: XSDT 00000000cf5e3080 0005C (v01 DELL    FX09    42302E31 AWRD 00000000)
ACPI: FACP 00000000cf5e7200 000F4 (v03 DELL    FX09    42302E31 AWRD 00000000)
ACPI: DSDT 00000000cf5e3200 03FFC (v01 DELL   AWRDACPI 00001000 MSFT 03000000)
ACPI: FACS 00000000cf590000 00040
ACPI: HPET 00000000cf5e73c0 00038 (v01 DELL    FX09    42302E31 AWRD 00000098)
ACPI: MCFG 00000000cf5e7400 0003C (v01 DELL    FX09    42302E31 AWRD 00000000)
ACPI: DMY1 00000000cf5e7440 00176 (v01 DELL    FX09    42302E31 AWRD 00000000)
ACPI: DMY2 00000000cf5e75c0 00080 (v01 DELL    FX09    42302E31 AWRD 00000000)
ACPI: APIC 00000000cf5e7300 00084 (v01 DELL    FX09    42302E31 AWRD 00000000)
ACPI: SSDT 00000000cf5e7f60 00380 (v01  PmRef    CpuPm 00003000 INTL 20041203)
ACPI: Local APIC address 0xfee00000
(8 early reservations) ==> bootmem [0000000000 - 01b0000000]
  #0 [0000000000 - 0000001000]   BIOS data page ==> [0000000000 - 0000001000]
  #1 [0000006000 - 0000008000]       TRAMPOLINE ==> [0000006000 - 0000008000]
  #2 [0001000000 - 00016837d0]    TEXT DATA BSS ==> [0001000000 - 00016837d0]
  #3 [0037ef1000 - 0037fef9a7]          RAMDISK ==> [0037ef1000 - 0037fef9a7]
  #4 [0000099c00 - 0000100000]    BIOS reserved ==> [0000099c00 - 0000100000]
  #5 [0001684000 - 00016840f8]              BRK ==> [0001684000 - 00016840f8]
  #6 [0000008000 - 000000c000]          PGTABLE ==> [0000008000 - 000000c000]
  #7 [000000c000 - 000000f000]          PGTABLE ==> [000000c000 - 000000f000]
found SMP MP-table at [ffff8800000f3f00] f3f00
 [ffffea0000000000-ffffea0005ffffff] PMD -> [ffff880028600000-ffff88002dbfffff] on node 0
Zone PFN ranges:
  DMA      0x00000000 -> 0x00001000
  DMA32    0x00001000 -> 0x00100000
  Normal   0x00100000 -> 0x001b0000
Movable zone start PFN for each node
early_node_map[4] active PFN ranges
    0: 0x00000000 -> 0x00000001
    0: 0x00000006 -> 0x00000099
    0: 0x00000100 -> 0x000cf590
    0: 0x00100000 -> 0x001b0000
On node 0 totalpages: 1570084
  DMA zone: 56 pages used for memmap
  DMA zone: 112 pages reserved
  DMA zone: 3820 pages, LIFO batch:0
  DMA32 zone: 14280 pages used for memmap
  DMA32 zone: 830920 pages, LIFO batch:31
  Normal zone: 9856 pages used for memmap
  Normal zone: 711040 pages, LIFO batch:31
ACPI: PM-Timer IO Port: 0x408
ACPI: Local APIC address 0xfee00000
ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
ACPI: LAPIC (acpi_id[0x01] lapic_id[0x01] enabled)
ACPI: LAPIC (acpi_id[0x02] lapic_id[0x03] enabled)
ACPI: LAPIC (acpi_id[0x03] lapic_id[0x02] enabled)
ACPI: LAPIC_NMI (acpi_id[0x00] high edge lint[0x1])
ACPI: LAPIC_NMI (acpi_id[0x01] high edge lint[0x1])
ACPI: LAPIC_NMI (acpi_id[0x02] high edge lint[0x1])
ACPI: LAPIC_NMI (acpi_id[0x03] high edge lint[0x1])
ACPI: IOAPIC (id[0x04] address[0xfec00000] gsi_base[0])
IOAPIC[0]: apic_id 4, version 32, address 0xfec00000, GSI 0-23
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
ACPI: IRQ0 used by override.
ACPI: IRQ2 used by override.
ACPI: IRQ9 used by override.
Using ACPI (MADT) for SMP configuration information
ACPI: HPET id: 0x8086a201 base: 0xfed00000
SMP: Allowing 4 CPUs, 0 hotplug CPUs
nr_irqs_gsi: 24
PM: Registered nosave memory: 0000000000001000 - 0000000000006000
PM: Registered nosave memory: 0000000000099000 - 000000000009a000
PM: Registered nosave memory: 000000000009a000 - 00000000000a0000
PM: Registered nosave memory: 00000000000a0000 - 00000000000f0000
PM: Registered nosave memory: 00000000000f0000 - 0000000000100000
PM: Registered nosave memory: 00000000cf590000 - 00000000cf5e3000
PM: Registered nosave memory: 00000000cf5e3000 - 00000000cf5f0000
PM: Registered nosave memory: 00000000cf5f0000 - 00000000cf600000
PM: Registered nosave memory: 00000000cf600000 - 00000000e0000000
PM: Registered nosave memory: 00000000e0000000 - 00000000f0000000
PM: Registered nosave memory: 00000000f0000000 - 00000000fec00000
PM: Registered nosave memory: 00000000fec00000 - 0000000100000000
Allocating PCI resources starting at cf600000 (gap: cf600000:10a00000)
NR_CPUS:16 nr_cpumask_bits:16 nr_cpu_ids:4 nr_node_ids:1
PERCPU: Embedded 28 pages at ffff880028034000, static data 82400 bytes
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 1545780
Kernel command line: root=/dev/disk/by-uuid/e9367b57-da02-48bf-9cd7-d41ce53520a3 ro
PID hash table entries: 4096 (order: 12, 32768 bytes)
Dentry cache hash table entries: 1048576 (order: 11, 8388608 bytes)
Inode-cache hash table entries: 524288 (order: 10, 4194304 bytes)
Initializing CPU#0
Checking aperture...
No AGP bridge found
Calgary: detecting Calgary via BIOS EBDA area
Calgary: Unable to locate Rio Grande table in EBDA - bailing!
PCI-DMA: Using software bounce buffering for IO (SWIOTLB)
Placing 64MB software IO TLB between ffff880020000000 - ffff880024000000
software IO TLB at phys 0x20000000 - 0x24000000
Memory: 6104592k/7077888k available (3629k kernel code, 797552k absent, 174760k reserved, 1500k data, 484k init)
SLUB: Genslabs=13, HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
NR_IRQS:768
Fast TSC calibration using PIT
Detected 2393.837 MHz processor.
Console: colour VGA+ 80x25
console [tty0] enabled
hpet clockevent registered
HPET: 4 timers in total, 0 timers will be used for per-cpu timer
Calibrating delay loop (skipped), value calculated using timer frequency.. 4789.16 BogoMIPS (lpj=7979456)
Security Framework initialized
Mount-cache hash table entries: 256
CPU: L1 I cache: 32K, L1 D cache: 32K
CPU: L2 cache: 4096K
CPU: Physical Processor ID: 0
CPU: Processor Core ID: 0
mce: CPU supports 6 MCE banks
CPU0: Thermal monitoring enabled (TM2)
using mwait in idle threads.
Performance Counters: Core2 events, Intel PMU driver.
... version:                 2
... bit width:               40
... generic counters:        2
... value mask:              000000ffffffffff
... max period:              000000007fffffff
... fixed-purpose counters:  3
... counter mask:            0000000700000003
ACPI: Core revision 20090521
Setting APIC routing to flat
..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
CPU0: Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz stepping 0b
Booting processor 1 APIC 0x1 ip 0x6000
Initializing CPU#1
Calibrating delay using timer specific routine.. 4789.48 BogoMIPS (lpj=7979981)
CPU: L1 I cache: 32K, L1 D cache: 32K
CPU: L2 cache: 4096K
CPU: Physical Processor ID: 0
CPU: Processor Core ID: 1
mce: CPU supports 6 MCE banks
CPU1: Thermal monitoring enabled (TM2)
x86 PAT enabled: cpu 1, old 0x7040600070406, new 0x7010600070106
CPU1: Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz stepping 0b
checking TSC synchronization [CPU#0 -> CPU#1]: passed.
Booting processor 2 APIC 0x3 ip 0x6000
Initializing CPU#2
Calibrating delay using timer specific routine.. 4789.51 BogoMIPS (lpj=7980021)
CPU: L1 I cache: 32K, L1 D cache: 32K
CPU: L2 cache: 4096K
CPU: Physical Processor ID: 0
CPU: Processor Core ID: 3
mce: CPU supports 6 MCE banks
CPU2: Thermal monitoring enabled (TM2)
x86 PAT enabled: cpu 2, old 0x7040600070406, new 0x7010600070106
CPU2: Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz stepping 0b
checking TSC synchronization [CPU#0 -> CPU#2]: passed.
Booting processor 3 APIC 0x2 ip 0x6000
Initializing CPU#3
Calibrating delay using timer specific routine.. 4789.56 BogoMIPS (lpj=7980102)
CPU: L1 I cache: 32K, L1 D cache: 32K
CPU: L2 cache: 4096K
CPU: Physical Processor ID: 0
CPU: Processor Core ID: 2
mce: CPU supports 6 MCE banks
CPU3: Thermal monitoring enabled (TM2)
x86 PAT enabled: cpu 3, old 0x7040600070406, new 0x7010600070106
CPU3: Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz stepping 0b
checking TSC synchronization [CPU#0 -> CPU#3]: passed.
Brought up 4 CPUs
Total of 4 processors activated (19159.72 BogoMIPS).
CPU0 attaching sched-domain:
 domain 0: span 0-1 level MC
  groups: 0 1
  domain 1: span 0-3 level CPU
   groups: 0-1 2-3
CPU1 attaching sched-domain:
 domain 0: span 0-1 level MC
  groups: 1 0
  domain 1: span 0-3 level CPU
   groups: 0-1 2-3
CPU2 attaching sched-domain:
 domain 0: span 2-3 level MC
  groups: 2 3
  domain 1: span 0-3 level CPU
   groups: 2-3 0-1
CPU3 attaching sched-domain:
 domain 0: span 2-3 level MC
  groups: 3 2
  domain 1: span 0-3 level CPU
   groups: 2-3 0-1
Booting paravirtualized kernel on bare hardware
NET: Registered protocol family 16
ACPI: bus type pci registered
PCI: MCFG configuration 0: base e0000000 segment 0 buses 0 - 255
PCI: MCFG area at e0000000 reserved in E820
PCI: Using MMCONFIG at e0000000 - efffffff
PCI: Using configuration type 1 for base access
mtrr: your CPUs had inconsistent fixed MTRR settings
mtrr: probably your BIOS does not setup all CPUs.
mtrr: corrected configuration.
bio: create slab <bio-0> at 0
ACPI: EC: Look up EC in DSDT
ACPI: Interpreter enabled
ACPI: (supports S0 S3 S4 S5)
ACPI: Using IOAPIC for interrupt routing
ACPI: No dock devices found.
ACPI: PCI Root Bridge [PCI0] (0000:00)
pci 0000:00:01.0: PME# supported from D0 D3hot D3cold
pci 0000:00:01.0: PME# disabled
pci 0000:00:02.0: reg 10 32bit mmio: [0xfdf00000-0xfdf7ffff]
pci 0000:00:02.0: reg 14 io port: [0xff00-0xff07]
pci 0000:00:02.0: reg 18 32bit mmio: [0xd0000000-0xdfffffff]
pci 0000:00:02.0: reg 1c 32bit mmio: [0xfdc00000-0xfdcfffff]
pci 0000:00:19.0: reg 10 32bit mmio: [0xfdfc0000-0xfdfdffff]
pci 0000:00:19.0: reg 14 32bit mmio: [0xfdfff000-0xfdffffff]
pci 0000:00:19.0: reg 18 io port: [0xfe00-0xfe1f]
pci 0000:00:19.0: PME# supported from D0 D3hot D3cold
pci 0000:00:19.0: PME# disabled
pci 0000:00:1a.0: reg 20 io port: [0xfd00-0xfd1f]
pci 0000:00:1a.1: reg 20 io port: [0xfc00-0xfc1f]
pci 0000:00:1a.2: reg 20 io port: [0xfb00-0xfb1f]
pci 0000:00:1a.7: reg 10 32bit mmio: [0xfdffe000-0xfdffe3ff]
pci 0000:00:1a.7: PME# supported from D0 D3hot D3cold
pci 0000:00:1a.7: PME# disabled
pci 0000:00:1d.0: reg 20 io port: [0xfa00-0xfa1f]
pci 0000:00:1d.1: reg 20 io port: [0xf900-0xf91f]
pci 0000:00:1d.2: reg 20 io port: [0xf800-0xf81f]
pci 0000:00:1d.7: reg 10 32bit mmio: [0xfdffd000-0xfdffd3ff]
pci 0000:00:1d.7: PME# supported from D0 D3hot D3cold
pci 0000:00:1d.7: PME# disabled
pci 0000:00:1f.0: quirk: region 0400-047f claimed by ICH6 ACPI/GPIO/TCO
pci 0000:00:1f.0: quirk: region 0480-04bf claimed by ICH6 GPIO
pci 0000:00:1f.0: ICH7 LPC Generic IO decode 1 PIO at 0800 (mask 003f)
pci 0000:00:1f.0: ICH7 LPC Generic IO decode 2 PIO at 0290 (mask 003f)
pci 0000:00:1f.2: reg 10 io port: [0xf700-0xf707]
pci 0000:00:1f.2: reg 14 io port: [0xf600-0xf603]
pci 0000:00:1f.2: reg 18 io port: [0xf500-0xf507]
pci 0000:00:1f.2: reg 1c io port: [0xf400-0xf403]
pci 0000:00:1f.2: reg 20 io port: [0xf300-0xf31f]
pci 0000:00:1f.2: reg 24 32bit mmio: [0xfdffc000-0xfdffc7ff]
pci 0000:00:1f.2: PME# supported from D3hot
pci 0000:00:1f.2: PME# disabled
pci 0000:00:1f.3: reg 10 64bit mmio: [0xfdffb000-0xfdffb0ff]
pci 0000:00:1f.3: reg 20 io port: [0x500-0x51f]
pci 0000:00:01.0: bridge io port: [0xd000-0xdfff]
pci 0000:00:01.0: bridge 32bit mmio: [0xfda00000-0xfdafffff]
pci 0000:00:01.0: bridge 64bit mmio pref: [0xfdb00000-0xfdbfffff]
pci 0000:02:01.0: reg 10 io port: [0xcf00-0xcf3f]
pci 0000:02:01.0: supports D1 D2
pci 0000:02:01.1: reg 10 io port: [0xce00-0xce07]
pci 0000:02:01.1: supports D1 D2
pci 0000:02:01.2: reg 10 32bit mmio: [0xfdeff000-0xfdeff7ff]
pci 0000:02:01.2: reg 14 32bit mmio: [0xfdef8000-0xfdefbfff]
pci 0000:02:01.2: supports D1 D2
pci 0000:02:01.2: PME# supported from D0 D1 D2 D3hot
pci 0000:02:01.2: PME# disabled
pci 0000:00:1e.0: transparent bridge
pci 0000:00:1e.0: bridge io port: [0xc000-0xcfff]
pci 0000:00:1e.0: bridge 32bit mmio: [0xfde00000-0xfdefffff]
pci 0000:00:1e.0: bridge 64bit mmio pref: [0xfdd00000-0xfddfffff]
pci_bus 0000:00: on NUMA node 0
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.HUB0._PRT]
ACPI: PCI Interrupt Link [LNKA] (IRQs 3 4 *5 7 9 10 11 12 14 15)
ACPI: PCI Interrupt Link [LNKB] (IRQs 3 *4 5 7 9 10 11 12 14 15)
ACPI: PCI Interrupt Link [LNKC] (IRQs 3 4 5 7 9 10 *11 12 14 15)
ACPI: PCI Interrupt Link [LNKD] (IRQs 3 4 5 7 9 10 *11 12 14 15)
ACPI: PCI Interrupt Link [LNKE] (IRQs 3 4 5 7 9 *10 11 12 14 15)
ACPI: PCI Interrupt Link [LNKF] (IRQs 3 4 5 7 9 *10 11 12 14 15)
ACPI: PCI Interrupt Link [LNK0] (IRQs *3 4 5 7 9 10 11 12 14 15)
ACPI: PCI Interrupt Link [LNK1] (IRQs 3 4 5 7 *9 10 11 12 14 15)
PCI: Using ACPI for IRQ routing
NetLabel: Initializing
NetLabel:  domain hash size = 128
NetLabel:  protocols = UNLABELED CIPSOv4
NetLabel:  unlabeled traffic allowed by default
pnp: PnP ACPI init
ACPI: bus type pnp registered
pnp: PnP ACPI: found 12 devices
ACPI: ACPI bus type pnp unregistered
system 00:01: ioport range 0x4d0-0x4d1 has been reserved
system 00:01: ioport range 0x800-0x87f has been reserved
system 00:01: ioport range 0x290-0x297 has been reserved
system 00:01: ioport range 0x880-0x88f has been reserved
system 00:08: ioport range 0x400-0x4bf could not be reserved
system 00:0a: iomem range 0xe0000000-0xefffffff has been reserved
system 00:0b: iomem range 0xf0000-0xfffff could not be reserved
system 00:0b: iomem range 0xcf600000-0xcf6fffff could not be reserved
system 00:0b: iomem range 0xfed00000-0xfed000ff has been reserved
system 00:0b: iomem range 0xcf590000-0xcf5fffff could not be reserved
system 00:0b: iomem range 0x0-0x9ffff could not be reserved
system 00:0b: iomem range 0x100000-0xcf58ffff could not be reserved
system 00:0b: iomem range 0xfec00000-0xfec00fff could not be reserved
system 00:0b: iomem range 0xfed14000-0xfed1dfff has been reserved
system 00:0b: iomem range 0xfed20000-0xfed9ffff has been reserved
system 00:0b: iomem range 0xfee00000-0xfee00fff has been reserved
system 00:0b: iomem range 0xffb00000-0xffb7ffff has been reserved
system 00:0b: iomem range 0xfff00000-0xffffffff has been reserved
system 00:0b: iomem range 0xe0000-0xeffff has been reserved
pci 0000:00:01.0: PCI bridge, secondary bus 0000:01
pci 0000:00:01.0:   IO window: 0xd000-0xdfff
pci 0000:00:01.0:   MEM window: 0xfda00000-0xfdafffff
pci 0000:00:01.0:   PREFETCH window: 0x000000fdb00000-0x000000fdbfffff
pci 0000:00:1e.0: PCI bridge, secondary bus 0000:02
pci 0000:00:1e.0:   IO window: 0xc000-0xcfff
pci 0000:00:1e.0:   MEM window: 0xfde00000-0xfdefffff
pci 0000:00:1e.0:   PREFETCH window: 0x000000fdd00000-0x000000fddfffff
pci 0000:00:01.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
pci 0000:00:01.0: setting latency timer to 64
pci 0000:00:1e.0: setting latency timer to 64
pci_bus 0000:00: resource 0 io:  [0x00-0xffff]
pci_bus 0000:00: resource 1 mem: [0x000000-0xffffffffffffffff]
pci_bus 0000:01: resource 0 io:  [0xd000-0xdfff]
pci_bus 0000:01: resource 1 mem: [0xfda00000-0xfdafffff]
pci_bus 0000:01: resource 2 pref mem [0xfdb00000-0xfdbfffff]
pci_bus 0000:02: resource 0 io:  [0xc000-0xcfff]
pci_bus 0000:02: resource 1 mem: [0xfde00000-0xfdefffff]
pci_bus 0000:02: resource 2 pref mem [0xfdd00000-0xfddfffff]
pci_bus 0000:02: resource 3 io:  [0x00-0xffff]
pci_bus 0000:02: resource 4 mem: [0x000000-0xffffffffffffffff]
NET: Registered protocol family 2
IP route cache hash table entries: 262144 (order: 9, 2097152 bytes)
TCP established hash table entries: 262144 (order: 10, 4194304 bytes)
TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
TCP: Hash tables configured (established 262144 bind 65536)
TCP reno registered
NET: Registered protocol family 1
Unpacking initramfs...
Freeing initrd memory: 1018k freed
Scanning for low memory corruption every 60 seconds
audit: initializing netlink socket (disabled)
type=2000 audit(1256998169.436:1): initialized
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
msgmni has been set to 11926
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
pci 0000:00:02.0: Boot video device
pcieport-driver 0000:00:01.0: irq 24 for MSI/MSI-X
pcieport-driver 0000:00:01.0: setting latency timer to 64
Linux agpgart interface v0.103
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
input: Macintosh mouse button emulation as /devices/virtual/input/input0
PNP: No PS/2 controller found. Probing ports directly.
serio: i8042 KBD port at 0x60,0x64 irq 1
serio: i8042 AUX port at 0x60,0x64 irq 12
mice: PS/2 mouse device common for all mice
cpuidle: using governor ladder
cpuidle: using governor menu
TCP cubic registered
NET: Registered protocol family 17
registered taskstats version 1
Initalizing network drop monitor service
Freeing unused kernel memory: 484k freed
agpgart-intel 0000:00:00.0: Intel G33 Chipset
agpgart-intel 0000:00:00.0: detected 7164K stolen memory
agpgart-intel 0000:00:00.0: AGP aperture is 256M @ 0xd0000000
[drm] Initialized drm 1.1.0 20060810
i915 0000:00:02.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
i915 0000:00:02.0: setting latency timer to 64
mtrr: no more MTRRs available
[drm] MTRR allocation failed.  Graphics performance may suffer.
i915 0000:00:02.0: irq 25 for MSI/MSI-X
Switched to high resolution mode on CPU 1
Switched to high resolution mode on CPU 3
Switched to high resolution mode on CPU 2
Switched to high resolution mode on CPU 0
[drm] DAC-6: set mode 1920x1080 11
Console: switching to colour frame buffer device 240x67
[drm] fb0: inteldrmfb frame buffer device
[drm] Initialized i915 1.6.0 20080730 for 0000:00:02.0 on minor 0
FDC 0 is a post-1991 82077
SCSI subsystem initialized
libata version 3.00 loaded.
ahci 0000:00:1f.2: version 3.0
ahci 0000:00:1f.2: PCI INT A -> GSI 19 (level, low) -> IRQ 19
ahci 0000:00:1f.2: irq 26 for MSI/MSI-X
ahci 0000:00:1f.2: AHCI 0001.0200 32 slots 6 ports 3 Gbps 0x3f impl RAID mode
ahci 0000:00:1f.2: flags: 64bit ncq sntf led clo pmp pio slum part ems 
ahci 0000:00:1f.2: setting latency timer to 64
scsi0 : ahci
scsi1 : ahci
scsi2 : ahci
scsi3 : ahci
scsi4 : ahci
scsi5 : ahci
ata1: SATA max UDMA/133 abar m2048@0xfdffc000 port 0xfdffc100 irq 26
ata2: SATA max UDMA/133 abar m2048@0xfdffc000 port 0xfdffc180 irq 26
ata3: SATA max UDMA/133 abar m2048@0xfdffc000 port 0xfdffc200 irq 26
ata4: SATA max UDMA/133 abar m2048@0xfdffc000 port 0xfdffc280 irq 26
ata5: SATA max UDMA/133 abar m2048@0xfdffc000 port 0xfdffc300 irq 26
ata6: SATA max UDMA/133 abar m2048@0xfdffc000 port 0xfdffc380 irq 26
ata3: SATA link down (SStatus 0 SControl 300)
ata2: SATA link down (SStatus 0 SControl 300)
ata4: SATA link down (SStatus 0 SControl 300)
ata6: SATA link down (SStatus 0 SControl 300)
ata5: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 300)
ata5.00: ATAPI: PLDS DVD+/-RW DH-16A6S, YD11, max UDMA/100
ata5.00: configured for UDMA/100
ata1.00: ATA-7: SAMSUNG HD322HJ, 1AC01113, max UDMA7
ata1.00: 625142448 sectors, multi 0: LBA48 NCQ (depth 31/32)
ata1.00: configured for UDMA/133
scsi 0:0:0:0: Direct-Access     ATA      SAMSUNG HD322HJ  1AC0 PQ: 0 ANSI: 5
scsi 4:0:0:0: CD-ROM            PLDS     DVD+-RW DH-16A6S YD11 PQ: 0 ANSI: 5
sd 0:0:0:0: [sda] 625142448 512-byte logical blocks: (320 GB/298 GiB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
 sda: sda1 sda2 sda3 sda4 < sda5 sda6 >
sd 0:0:0:0: [sda] Attached SCSI disk
sr0: scsi3-mmc drive: 48x/12x writer dvd-ram cd/rw xa/form2 cdda tray
Uniform CD-ROM driver Revision: 3.20
sr 4:0:0:0: Attached scsi CD-ROM sr0
EXT4-fs (sda2): barriers enabled
kjournald2 starting: pid 557, dev sda2:8, commit interval 5 seconds
EXT4-fs (sda2): delayed allocation enabled
EXT4-fs: file extents enabled
EXT4-fs: mballoc enabled
EXT4-fs (sda2): mounted filesystem with ordered data mode
rtc_cmos 00:04: RTC can wake from S4
rtc_cmos 00:04: rtc core: registered rtc_cmos as rtc0
rtc0: alarms up to one month, 242 bytes nvram, hpet irqs
udev: starting version 146
i801_smbus 0000:00:1f.3: PCI INT B -> GSI 18 (level, low) -> IRQ 18
input: PC Speaker as /devices/platform/pcspkr/input/input1
input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input2
ACPI: Power Button [PWRF]
input: Power Button as /devices/LNXSYSTM:00/device:00/PNP0C0C:00/input/input3
ACPI: Power Button [PWRB]
dcdbas dcdbas: Dell Systems Management Base Driver (version 5.6.0-3.2)
e1000e: Intel(R) PRO/1000 Network Driver - 1.0.2-k2
e1000e: Copyright (c) 1999-2008 Intel Corporation.
e1000e 0000:00:19.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
e1000e 0000:00:19.0: pci_enable_pcie_error_reporting failed 0xfffffffb
e1000e 0000:00:19.0: setting latency timer to 64
e1000e 0000:00:19.0: irq 27 for MSI/MSI-X
iTCO_vendor_support: vendor-support=0
sd 0:0:0:0: Attached scsi generic sg0 type 0
sr 4:0:0:0: Attached scsi generic sg1 type 5
ACPI: SSDT 00000000cf5e7680 0022A (v01  PmRef  Cpu0Ist 00003000 INTL 20041203)
processor LNXCPU:00: registered as cooling_device0
ACPI: SSDT 00000000cf5e7b40 00152 (v01  PmRef  Cpu1Ist 00003000 INTL 20041203)
processor LNXCPU:01: registered as cooling_device1
ACPI: SSDT 00000000cf5e7ca0 00152 (v01  PmRef  Cpu2Ist 00003000 INTL 20041203)
processor LNXCPU:02: registered as cooling_device2
ACPI: SSDT 00000000cf5e7e00 00152 (v01  PmRef  Cpu3Ist 00003000 INTL 20041203)
processor LNXCPU:03: registered as cooling_device3
iTCO_wdt: Intel TCO WatchDog Timer Driver v1.05
iTCO_wdt: Found a ICH9R TCO device (Version=2, TCOBASE=0x0460)
iTCO_wdt: initialized. heartbeat=30 sec (nowayout=0)
gameport: EMU10K1 is pci0000:02:01.1/gameport0, io 0xce00, speed 1007kHz
fan PNP0C0B:00: registered as cooling_device4
ACPI: Fan [FAN] (on)
thermal LNXTHERM:01: registered as thermal_zone0
ACPI: Thermal Zone [THRM] (40 C)
0000:00:19.0: eth0: (PCI Express:2.5GB/s:Width x1) 00:21:9b:06:4c:c9
0000:00:19.0: eth0: Intel(R) PRO/10/100 Network Connection
0000:00:19.0: eth0: MAC: 7, PHY: 7, PBA No: ffffff-0ff
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
ohci1394 0000:02:01.2: PCI INT B -> GSI 17 (level, low) -> IRQ 17
ohci1394 0000:02:01.2: setting latency timer to 64
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci_hcd 0000:00:1a.7: PCI INT C -> GSI 18 (level, low) -> IRQ 18
ehci_hcd 0000:00:1a.7: setting latency timer to 64
ehci_hcd 0000:00:1a.7: EHCI Host Controller
ehci_hcd 0000:00:1a.7: new USB bus registered, assigned bus number 1
ehci_hcd 0000:00:1a.7: debug port 1
ehci_hcd 0000:00:1a.7: cache line size of 32 is not supported
ehci_hcd 0000:00:1a.7: irq 18, io mem 0xfdffe000
ehci_hcd 0000:00:1a.7: USB 2.0 started, EHCI 1.00
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 6 ports detected
ehci_hcd 0000:00:1d.7: PCI INT A -> GSI 23 (level, low) -> IRQ 23
ehci_hcd 0000:00:1d.7: setting latency timer to 64
ehci_hcd 0000:00:1d.7: EHCI Host Controller
ehci_hcd 0000:00:1d.7: new USB bus registered, assigned bus number 2
ohci1394: fw-host0: OHCI-1394 1.1 (PCI): IRQ=[17]  MMIO=[fdeff000-fdeff7ff]  Max Packet=[2048]  IR/IT contexts=[4/8]
ehci_hcd 0000:00:1d.7: debug port 1
ehci_hcd 0000:00:1d.7: cache line size of 32 is not supported
ehci_hcd 0000:00:1d.7: irq 23, io mem 0xfdffd000
ehci_hcd 0000:00:1d.7: USB 2.0 started, EHCI 1.00
usb usb2: configuration #1 chosen from 1 choice
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 6 ports detected
uhci_hcd: USB Universal Host Controller Interface driver
uhci_hcd 0000:00:1a.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
uhci_hcd 0000:00:1a.0: setting latency timer to 64
uhci_hcd 0000:00:1a.0: UHCI Host Controller
uhci_hcd 0000:00:1a.0: new USB bus registered, assigned bus number 3
uhci_hcd 0000:00:1a.0: irq 16, io base 0x0000fd00
usb usb3: configuration #1 chosen from 1 choice
hub 3-0:1.0: USB hub found
hub 3-0:1.0: 2 ports detected
uhci_hcd 0000:00:1a.1: PCI INT B -> GSI 21 (level, low) -> IRQ 21
uhci_hcd 0000:00:1a.1: setting latency timer to 64
uhci_hcd 0000:00:1a.1: UHCI Host Controller
uhci_hcd 0000:00:1a.1: new USB bus registered, assigned bus number 4
uhci_hcd 0000:00:1a.1: irq 21, io base 0x0000fc00
usb usb4: configuration #1 chosen from 1 choice
hub 4-0:1.0: USB hub found
hub 4-0:1.0: 2 ports detected
uhci_hcd 0000:00:1a.2: PCI INT D -> GSI 19 (level, low) -> IRQ 19
uhci_hcd 0000:00:1a.2: setting latency timer to 64
uhci_hcd 0000:00:1a.2: UHCI Host Controller
uhci_hcd 0000:00:1a.2: new USB bus registered, assigned bus number 5
uhci_hcd 0000:00:1a.2: irq 19, io base 0x0000fb00
usb usb5: configuration #1 chosen from 1 choice
hub 5-0:1.0: USB hub found
hub 5-0:1.0: 2 ports detected
uhci_hcd 0000:00:1d.0: PCI INT A -> GSI 23 (level, low) -> IRQ 23
uhci_hcd 0000:00:1d.0: setting latency timer to 64
uhci_hcd 0000:00:1d.0: UHCI Host Controller
uhci_hcd 0000:00:1d.0: new USB bus registered, assigned bus number 6
uhci_hcd 0000:00:1d.0: irq 23, io base 0x0000fa00
usb usb6: configuration #1 chosen from 1 choice
hub 6-0:1.0: USB hub found
hub 6-0:1.0: 2 ports detected
uhci_hcd 0000:00:1d.1: PCI INT B -> GSI 19 (level, low) -> IRQ 19
uhci_hcd 0000:00:1d.1: setting latency timer to 64
uhci_hcd 0000:00:1d.1: UHCI Host Controller
uhci_hcd 0000:00:1d.1: new USB bus registered, assigned bus number 7
uhci_hcd 0000:00:1d.1: irq 19, io base 0x0000f900
usb usb7: configuration #1 chosen from 1 choice
hub 7-0:1.0: USB hub found
hub 7-0:1.0: 2 ports detected
uhci_hcd 0000:00:1d.2: PCI INT C -> GSI 18 (level, low) -> IRQ 18
uhci_hcd 0000:00:1d.2: setting latency timer to 64
uhci_hcd 0000:00:1d.2: UHCI Host Controller
uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 8
uhci_hcd 0000:00:1d.2: irq 18, io base 0x0000f800
usb usb8: configuration #1 chosen from 1 choice
hub 8-0:1.0: USB hub found
hub 8-0:1.0: 2 ports detected
EMU10K1_Audigy 0000:02:01.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
EMU10K1_Audigy 0000:02:01.0: setting latency timer to 64
Installing spdif_bug patch: SB Audigy 2 ZS [SB0350]
usb 5-1: new full speed USB device using uhci_hcd and address 2
usb 5-1: configuration #1 chosen from 1 choice
hub 5-1:1.0: USB hub found
hub 5-1:1.0: 4 ports detected
usb 5-1.1: new low speed USB device using uhci_hcd and address 3
usb 5-1.1: configuration #1 chosen from 1 choice
ieee1394: Host added: ID:BUS[0-00:1023]  GUID[00023c01510c1ac4]
usb 5-1.3: new low speed USB device using uhci_hcd and address 4
usbcore: registered new interface driver hiddev
input: Logitech Logitech Gaming Keyboard as /devices/pci0000:00/0000:00:1a.2/usb5/5-1/5-1.1/5-1.1:1.0/input/input4
generic-usb 0003:046D:C221.0001: input,hidraw0: USB HID v1.10 Keyboard [Logitech Logitech Gaming Keyboard] on usb-0000:00:1a.2-1.1/input0
input: Logitech Logitech Gaming Keyboard as /devices/pci0000:00/0000:00:1a.2/usb5/5-1/5-1.1/5-1.1:1.1/input/input5
generic-usb 0003:046D:C221.0002: input,hiddev0,hidraw1: USB HID v1.10 Device [Logitech Logitech Gaming Keyboard] on usb-0000:00:1a.2-1.1/input1
usbcore: registered new interface driver usbhid
usbhid: v2.6:USB HID core driver
usb 5-1.3: configuration #1 chosen from 1 choice
input: Logitech USB-PS/2 Optical Mouse as /devices/pci0000:00/0000:00:1a.2/usb5/5-1/5-1.3/5-1.3:1.0/input/input6
generic-usb 0003:046D:C01E.0003: input,hidraw2: USB HID v1.10 Mouse [Logitech USB-PS/2 Optical Mouse] on usb-0000:00:1a.2-1.3/input0
usb 5-1.4: new full speed USB device using uhci_hcd and address 5
usb 5-1.4: configuration #1 chosen from 1 choice
input: G15 Keyboard G15 Keyboard as /devices/pci0000:00/0000:00:1a.2/usb5/5-1/5-1.4/5-1.4:1.0/input/input7
generic-usb 0003:046D:C222.0004: input,hiddev1,hidraw3: USB HID v1.11 Keypad [G15 Keyboard G15 Keyboard] on usb-0000:00:1a.2-1.4/input0
EXT4-fs (sda2): internal journal on sda2:8
EXT4-fs (sda5): barriers enabled
kjournald2 starting: pid 1140, dev sda5:8, commit interval 5 seconds
EXT4-fs (sda5): internal journal on sda5:8
EXT4-fs (sda5): Ignoring delalloc option - requested data journaling mode
EXT4-fs: file extents enabled
EXT4-fs: mballoc enabled
EXT4-fs (sda5): mounted filesystem with journalled data mode
EXT4-fs (sda6): barriers enabled
kjournald2 starting: pid 1143, dev sda6:8, commit interval 5 seconds
EXT4-fs (sda6): internal journal on sda6:8
EXT4-fs (sda6): delayed allocation enabled
EXT4-fs: file extents enabled
EXT4-fs: mballoc enabled
EXT4-fs (sda6): mounted filesystem with ordered data mode
loop: module loaded
Adding 3212992k swap on /dev/sda3.  Priority:-1 extents:1 across:3212992k 
e1000e 0000:00:19.0: irq 27 for MSI/MSI-X
e1000e 0000:00:19.0: irq 27 for MSI/MSI-X
ip_tables: (C) 2000-2006 Netfilter Core Team
nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Please use
nf_conntrack.acct=1 kernel parameter, acct=1 nf_conntrack module option or
sysctl net.netfilter.nf_conntrack_acct=1 to enable it.
e1000e: eth0 NIC Link is Up 100 Mbps Full Duplex, Flow Control: RX/TX
0000:00:19.0: eth0: 10/100 speed: disabling TSO
NET: Registered protocol family 10
lo: Disabled Privacy Extensions
eth0: no IPv6 routers present

^ permalink raw reply

* kerneloops.org report for the week of October 31 2009
From: Arjan van de Ven @ 2009-10-31 23:03 UTC (permalink / raw)
  To: linux-kernel, torvalds
  Cc: linux-acpi, tytso, netdev, Eric Paris, akpm, Matt Domsch


This week, a total of 18023 oopses and warnings have been reported,
compared to 5816 reports in the previous week. This number and this
report only includes kernel 2.6.31 and later.

This week, the Ubuntu 9.10 distribution got released, which includes
kerneloops.org integration in the quality feedback system. I'd like
to thank the Ubuntu team for their effort in helping to get the quality
feedback about the kernel integrated into kerneloops.org.


One thing to note is that the Ubuntu 9.10 release ships with the kernel
debug option CONFIG_PM_TEST_SUSPEND enabled, causing many warnings to 
be submitted. This huge volume triggered me to split these reports, as well
as the check_bios_for_corruption() reports into a per machine entry.

The top 5 machines for which the suspend test fails:
   319 | suspend_test_finish(Latitude D830)
   231 | suspend_test_finish(XPS M1530)
   225 | suspend_test_finish(MacBook2,1)
   171 | suspend_test_finish(Compaq Presario CQ60 Notebook PC)
   157 | suspend_test_finish(Studio XPS 1340)

and there is also the very elegant 
   267 | suspend_test_finish(To Be Filled By O.E.M)


The top 5 machines where the BIOS corrupts memory:
    80 | check_for_bios_corruption(HP Compaq nx6110)
    69 | check_for_bios_corruption(HP Compaq nc6120)
    62 | check_for_bios_corruption(HP Pavilion dv6700 Notebook PC)
    49 | check_for_bios_corruption(HP Pavilion dv2700 Notebook PC)
    32 | check_for_bios_corruption(Compaq Presario F700 Notebook PC)


The report this week looks different from previous reports; the version
cut-off has moved to 2.6.31 so that a lot of older bugs now dropped out of the report.

New this week are some inotify bugs, that have been fixed in Linus' git tree after -rc5.
There's also an ext2 warning for when the user unplugs a USB stick, as well as the
usual binary and external kernel modules.

If you have (better) descriptions for some of these, let me know and I can add them to the
database.




Rank 1: suspend_test_finish(System Product Name) (warning)
	Reported 930 times (1510 total reports)
	This warning was last seen in version 2.6.31, and first seen in 2.6.27.15.
	More info: http://www.kerneloops.org/searchweek.php?search=suspend_test_finish(System Product Name)

Rank 2: acpi_idle_enter_bm (oops)
	Reported 783 times (1924 total reports)
	This oops was last seen in version 2.6.32, and first seen in 2.6.23.8.
	More info: http://www.kerneloops.org/searchweek.php?search=acpi_idle_enter_bm

Rank 3: dev_watchdog(sis900) (warning)
	Reported 514 times (19593 total reports)
	This warning was last seen in version 2.6.31, and first seen in 2.6.26-rc4-git2.
	More info: http://www.kerneloops.org/searchweek.php?search=dev_watchdog(sis900)

Rank 4: suspend_test_finish(Unknown) (oops)
	Reported 431 times (5580 total reports)
	This oops was last seen in version 2.6.31, and first seen in 2.6.27.15.
	More info: http://www.kerneloops.org/searchweek.php?search=suspend_test_finish(Unknown)

Rank 5: tcp_recvmsg (oops)
	Reported 372 times (7133 total reports)
	This oops was last seen in version 2.6.31.3, and first seen in 2.6.25.
	More info: http://www.kerneloops.org/searchweek.php?search=tcp_recvmsg

Rank 6: inotify_remove_from_idr (oops)
	Reported 369 times (942 total reports)
	Fixed in commit 9f0d793b52eb
	This oops was last seen in version 2.6.32, and first seen in 2.6.31-rc8.
	More info: http://www.kerneloops.org/searchweek.php?search=inotify_remove_from_idr

Rank 7: ext2_sync_fs (warning)
	Reported 265 times (508 total reports)
	Caused by the user removing a USB stick while mounted
	This warning was last seen in version 2.6.32-rc5, and first seen in 2.6.30.
	More info: http://www.kerneloops.org/searchweek.php?search=ext2_sync_fs

Rank 8: ieee80211_scan_completed (oops)
	Reported 264 times (1494 total reports)
	This oops was last seen in version 2.6.32-rc2, and first seen in 2.6.27.29.
	More info: http://www.kerneloops.org/searchweek.php?search=ieee80211_scan_completed

Rank 9: wl_pci_probe (warning)
	Reported 216 times (251 total reports)
	[Ubuntu] Bug in a binary driver shipped by Ubuntu
	warning only shows up in tainted kernels
	This warning was last seen in version 2.6.31, and first seen in 2.6.30.8.
	More info: http://www.kerneloops.org/searchweek.php?search=wl_pci_probe

Rank 10: apparmor_bprm_set_creds (oops)
	Reported 201 times (324 total reports)
	NULL pointer dereference in AppArmor
	This oops was last seen in version 2.6.31, and first seen in 2.6.31.
	More info: http://www.kerneloops.org/searchweek.php?search=apparmor_bprm_set_creds

Rank 11: KCL_MEM_AllocContiguousPageFrames (warning)
	Reported 188 times (256 total reports)
	[tainted] The AMD binary graphics driver uses GFP_NOWARN on a high order allocation
	warning only shows up in tainted kernels
	This warning was last seen in version 2.6.31, and first seen in 2.6.31.
	More info: http://www.kerneloops.org/searchweek.php?search=KCL_MEM_AllocContiguousPageFrames

Rank 12: idr_callback (warning)
	Reported 174 times (638 total reports)
	Fixed in commit 9f0d793b52eb before 2.6.32-rc6
	This warning was last seen in version 2.6.32, and first seen in 2.6.31-rc4-git2.
	More info: http://www.kerneloops.org/searchweek.php?search=idr_callback


--
Arjan van de Ven 	Intel Open Source Technology Centre
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org

^ permalink raw reply

* Re: kerneloops.org report for the week of October 31 2009
From: Rafael J. Wysocki @ 2009-10-31 23:20 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: linux-kernel, torvalds, linux-acpi, tytso, netdev, Eric Paris,
	akpm, Matt Domsch
In-Reply-To: <20091031160351.26fcc6c5@infradead.org>

On Sunday 01 November 2009, Arjan van de Ven wrote:
> 
> This week, a total of 18023 oopses and warnings have been reported,
> compared to 5816 reports in the previous week. This number and this
> report only includes kernel 2.6.31 and later.
> 
> This week, the Ubuntu 9.10 distribution got released, which includes
> kerneloops.org integration in the quality feedback system. I'd like
> to thank the Ubuntu team for their effort in helping to get the quality
> feedback about the kernel integrated into kerneloops.org.
> 
> 
> One thing to note is that the Ubuntu 9.10 release ships with the kernel
> debug option CONFIG_PM_TEST_SUSPEND enabled, causing many warnings to 
> be submitted. This huge volume triggered me to split these reports, as well
> as the check_bios_for_corruption() reports into a per machine entry.
> 
> The top 5 machines for which the suspend test fails:
>    319 | suspend_test_finish(Latitude D830)
>    231 | suspend_test_finish(XPS M1530)
>    225 | suspend_test_finish(MacBook2,1)
>    171 | suspend_test_finish(Compaq Presario CQ60 Notebook PC)
>    157 | suspend_test_finish(Studio XPS 1340)
> 
> and there is also the very elegant 
>    267 | suspend_test_finish(To Be Filled By O.E.M)
> 
> 
> The top 5 machines where the BIOS corrupts memory:
>     80 | check_for_bios_corruption(HP Compaq nx6110)
>     69 | check_for_bios_corruption(HP Compaq nc6120)
>     62 | check_for_bios_corruption(HP Pavilion dv6700 Notebook PC)
>     49 | check_for_bios_corruption(HP Pavilion dv2700 Notebook PC)
>     32 | check_for_bios_corruption(Compaq Presario F700 Notebook PC)
> 
> 
> The report this week looks different from previous reports; the version
> cut-off has moved to 2.6.31 so that a lot of older bugs now dropped out of the report.
> 
> New this week are some inotify bugs, that have been fixed in Linus' git tree after -rc5.
> There's also an ext2 warning for when the user unplugs a USB stick, as well as the
> usual binary and external kernel modules.
> 
> If you have (better) descriptions for some of these, let me know and I can add them to the
> database.
> 
> 
> 
> 
> Rank 1: suspend_test_finish(System Product Name) (warning)
> 	Reported 930 times (1510 total reports)
> 	This warning was last seen in version 2.6.31, and first seen in 2.6.27.15.
> 	More info: http://www.kerneloops.org/searchweek.php?search=suspend_test_finish(System Product Name)

This should be fixed by commit 04bf7539c08d64184736cdc5e4ad617eda77eb0f
(PM: Make warning in suspend_test_finish() less likely to happen), at least on some
machines that report it.

Thanks,
Rafael

^ permalink raw reply

* Subject: [PATCH 6/6] bna: Brocade 10Gb Ethernet device driver
From: Rasesh Mody @ 2009-11-01  5:03 UTC (permalink / raw)
  To: netdev; +Cc: adapter_linux_open_src_team

From: Rasesh Mody <rmody@brocade.com>

This is patch 6/6 which contains linux driver source for
Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
Re-based source against net-next-2.6 and re-submitting the
patch with few fixes.

We wish this patch to be considered for inclusion in net-next-2.6

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 Kconfig      |   15 +++++++++++++++
 Makefile     |    1 +
 bna/Makefile |   17 +++++++++++++++++
 3 files changed, 33 insertions(+)

diff -ruP net-next-2.6-orig/drivers/net/Kconfig net-next-2.6-mod/drivers/net/Kconfig
--- net-next-2.6-orig/drivers/net/Kconfig	2009-10-31 00:44:29.000000000 -0700
+++ net-next-2.6-mod/drivers/net/Kconfig	2009-10-31 21:40:54.515921000 -0700
@@ -2757,6 +2757,21 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called qlge.
 
+config BNA
+        tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
+        depends on PCI
+        ---help---
+          This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
+          cards.
+
+          To compile this driver as a module, choose M here: the module
+          will be called bna.
+
+          For general information and support, go to the Brocade support
+          website at:
+
+          <http://support.brocade.com>
+
 source "drivers/net/sfc/Kconfig"
 
 source "drivers/net/benet/Kconfig"
diff -ruP net-next-2.6-orig/drivers/net/Makefile net-next-2.6-mod/drivers/net/Makefile
--- net-next-2.6-orig/drivers/net/Makefile	2009-10-31 00:44:29.000000000 -0700
+++ net-next-2.6-mod/drivers/net/Makefile	2009-10-31 21:40:54.533912000 -0700
@@ -31,6 +31,7 @@
 obj-$(CONFIG_JME) += jme.o
 obj-$(CONFIG_BE2NET) += benet/
 obj-$(CONFIG_VMXNET3) += vmxnet3/
+obj-$(CONFIG_BNA) += bna/
 
 gianfar_driver-objs := gianfar.o \
 		gianfar_ethtool.o \
diff -ruP net-next-2.6-orig/drivers/net/bna/Makefile net-next-2.6-mod/drivers/net/bna/Makefile
--- net-next-2.6-orig/drivers/net/bna/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/Makefile	2009-10-31 21:40:54.561914000 -0700
@@ -0,0 +1,17 @@
+#
+#    Copyright (c) 2005-2008 Brocade Communications Systems, Inc.
+#    All rights reserved.
+#
+
+obj-$(CONFIG_BNA) += bna.o
+
+bna-objs := bnad.o bnad_ethtool.o bna_fn.o bna_if.o bna_queue.o \
+		bfad_fwimg.o bfa_csdebug.o bfa_sm.o \
+		bfa_ioc.o bfa_timer.o \
+		bfa_cee.o
+
+EXTRA_CFLAGS += -Idrivers/net/bna \
+		-Idrivers/net/bna/include \
+		-Idrivers/net/bna/include/cee \
+		-Idrivers/net/bna/include/cna/pstats \
+		-Idrivers/net/bna/include/cs 

^ permalink raw reply

* Subject: [PATCH 3/6] bna: Brocade 10Gb Ethernet device driver
From: Rasesh Mody @ 2009-11-01  5:03 UTC (permalink / raw)
  To: netdev; +Cc: adapter_linux_open_src_team

From: Rasesh Mody <rmody@brocade.com>

This is patch 3/6 which contains linux driver source for
Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
Re-based source against net-next-2.6 and re-submitting the
patch with few fixes.

We wish this patch to be considered for inclusion in net-next-2.6

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 bfa_cee.c     |  463 +++++++++++
 bfa_csdebug.c |   62 +
 bfa_ioc.c     | 2273 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bfa_sm.c      |   45 +
 bna_if.c      |  588 +++++++++++++++
 bna_iocll.h   |   66 +
 bna_os.h      |  182 ++++
 bna_priv.h    |  490 ++++++++++++
 bnad_compat.h |   96 ++
 bnad_defs.h   |   36 
 cna.h         |   32 
 11 files changed, 4333 insertions(+)

diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_cee.c net-next-2.6-mod/drivers/net/bna/bfa_cee.c
--- net-next-2.6-orig/drivers/net/bna/bfa_cee.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_cee.c	2009-10-31 21:34:47.836534000 -0700
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#include <defs/bfa_defs_cee.h>
+#include <cs/bfa_debug.h>
+#include <cee/bfa_cee.h>
+#include <bfi/bfi_cee.h>
+#include <bfi/bfi.h>
+#include <bfa_ioc.h>
+
+
+#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
+
+static void     bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
+static void     bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
+					   *dcbcx_stats);
+static void     bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
+					  *lldp_stats);
+static void     bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
+static void     bfa_cee_format_cee_cfg(void *buffer);
+static void     bfa_cee_format_cee_stats(void *buffer);
+
+static void
+bfa_cee_format_cee_stats(void *buffer)
+{
+	struct bfa_cee_stats_s *cee_stats = buffer;
+	bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
+	bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
+	bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
+}
+
+static void
+bfa_cee_format_cee_cfg(void *buffer)
+{
+	struct bfa_cee_attr_s *cee_cfg = buffer;
+	bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
+}
+
+static void
+bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
+{
+	dcbcx_stats->subtlvs_unrecognized =
+		bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
+	dcbcx_stats->negotiation_failed =
+		bfa_os_ntohl(dcbcx_stats->negotiation_failed);
+	dcbcx_stats->remote_cfg_changed =
+		bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
+	dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
+	dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
+	dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
+	dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
+	dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
+	dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
+}
+
+static void
+bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
+{
+	lldp_stats->frames_transmitted =
+		bfa_os_ntohl(lldp_stats->frames_transmitted);
+	lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
+	lldp_stats->frames_discarded =
+		bfa_os_ntohl(lldp_stats->frames_discarded);
+	lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
+	lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
+	lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
+	lldp_stats->tlvs_unrecognized =
+		bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
+}
+
+static void
+bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
+{
+	cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
+	cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
+	cfg_stats->cee_hw_cfg_changed =
+		bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
+	cfg_stats->recvd_invalid_cfg =
+		bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
+}
+
+static void
+bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
+{
+	lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
+	lldp_cfg->enabled_system_cap =
+		bfa_os_ntohs(lldp_cfg->enabled_system_cap);
+}
+
+/**
+ * bfa_cee_attr_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static          u32
+bfa_cee_attr_meminfo(void)
+{
+	return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_cee_stats_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static          u32
+bfa_cee_stats_meminfo(void)
+{
+	return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+	cee->get_attr_status = status;
+	if (status == BFA_STATUS_OK) {
+		/*
+		 * The requested data has been copied to the DMA area, *process
+		 * it.
+		 */
+		memcpy(cee->attr, cee->attr_dma.kva,
+		       sizeof(struct bfa_cee_attr_s));
+		bfa_cee_format_cee_cfg(cee->attr);
+	}
+	cee->get_attr_pending = BFA_FALSE;
+	if (cee->cbfn.get_attr_cbfn)
+		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+	cee->get_stats_status = status;
+	if (status == BFA_STATUS_OK) {
+		/*
+		 * The requested data has been copied to the DMA area, process
+		 * it.
+		 */
+		memcpy(cee->stats, cee->stats_dma.kva,
+		       sizeof(struct bfa_cee_stats_s));
+		bfa_cee_format_cee_stats(cee->stats);
+	}
+	cee->get_stats_pending = BFA_FALSE;
+	if (cee->cbfn.get_stats_cbfn)
+		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+	cee->reset_stats_status = status;
+	cee->reset_stats_pending = BFA_FALSE;
+	if (cee->cbfn.reset_stats_cbfn)
+		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
+}
+
+/**
+ * bfa_cee_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_cee_meminfo(void)
+{
+	return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
+}
+
+/**
+ * bfa_cee_mem_claim()
+ *
+ *
+ * @param[in] cee CEE module pointer
+ * 	      dma_kva Kernel Virtual Address of CEE DMA Memory
+ * 	      dma_pa  Physical Address of CEE DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
+{
+	cee->attr_dma.kva = dma_kva;
+	cee->attr_dma.pa = dma_pa;
+	cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
+	cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
+	cee->attr = (struct bfa_cee_attr_s *)dma_kva;
+	cee->stats =
+		(struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
+}
+
+/**
+ * bfa_cee_get_attr()
+ *
+ *   Send the request to the f/w to fetch CEE attributes.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
+		 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_cee_get_req_s *cmd;
+
+	bfa_assert((cee != NULL) && (cee->ioc != NULL));
+	if (!bfa_ioc_is_operational(cee->ioc))
+		return BFA_STATUS_IOC_FAILURE;
+	if (cee->get_attr_pending == BFA_TRUE)
+		return BFA_STATUS_DEVBUSY;
+	cee->get_attr_pending = BFA_TRUE;
+	cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
+	cee->attr = attr;
+	cee->cbfn.get_attr_cbfn = cbfn;
+	cee->cbfn.get_attr_cbarg = cbarg;
+	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
+		    bfa_ioc_portid(cee->ioc));
+	bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
+	bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_cee_get_stats()
+ *
+ *   Send the request to the f/w to fetch CEE statistics.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
+		  bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_cee_get_req_s *cmd;
+
+	bfa_assert((cee != NULL) && (cee->ioc != NULL));
+
+	if (!bfa_ioc_is_operational(cee->ioc))
+		return BFA_STATUS_IOC_FAILURE;
+	if (cee->get_stats_pending == BFA_TRUE)
+		return BFA_STATUS_DEVBUSY;
+	cee->get_stats_pending = BFA_TRUE;
+	cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
+	cee->stats = stats;
+	cee->cbfn.get_stats_cbfn = cbfn;
+	cee->cbfn.get_stats_cbarg = cbarg;
+	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
+		    bfa_ioc_portid(cee->ioc));
+	bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
+	bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_cee_reset_stats()
+ *
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
+		    void *cbarg)
+{
+	struct bfi_cee_reset_stats_s *cmd;
+
+	bfa_assert((cee != NULL) && (cee->ioc != NULL));
+	if (!bfa_ioc_is_operational(cee->ioc))
+		return BFA_STATUS_IOC_FAILURE;
+	if (cee->reset_stats_pending == BFA_TRUE)
+		return BFA_STATUS_DEVBUSY;
+	cee->reset_stats_pending = BFA_TRUE;
+	cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
+	cee->cbfn.reset_stats_cbfn = cbfn;
+	cee->cbfn.reset_stats_cbarg = cbarg;
+	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
+		    bfa_ioc_portid(cee->ioc));
+	bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_cee_isrs()
+ *
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+void
+bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
+{
+	union bfi_cee_i2h_msg_u *msg;
+	struct bfi_cee_get_rsp_s *get_rsp;
+	struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
+	msg = (union bfi_cee_i2h_msg_u *)m;
+	get_rsp = (struct bfi_cee_get_rsp_s *)m;
+	switch (msg->mh.msg_id) {
+	case BFI_CEE_I2H_GET_CFG_RSP:
+		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
+		break;
+	case BFI_CEE_I2H_GET_STATS_RSP:
+		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
+		break;
+	case BFI_CEE_I2H_RESET_STATS_RSP:
+		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
+		break;
+	default:
+		bfa_assert(0);
+	}
+}
+
+/**
+ * bfa_cee_hbfail()
+ *
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+void
+bfa_cee_hbfail(void *arg)
+{
+	struct bfa_cee_s *cee;
+	cee = (struct bfa_cee_s *)arg;
+
+	if (cee->get_attr_pending == BFA_TRUE) {
+		cee->get_attr_status = BFA_STATUS_FAILED;
+		cee->get_attr_pending = BFA_FALSE;
+		if (cee->cbfn.get_attr_cbfn)
+			cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
+						BFA_STATUS_FAILED);
+	}
+	if (cee->get_stats_pending == BFA_TRUE) {
+		cee->get_stats_status = BFA_STATUS_FAILED;
+		cee->get_stats_pending = BFA_FALSE;
+		if (cee->cbfn.get_stats_cbfn)
+			cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
+						 BFA_STATUS_FAILED);
+	}
+	if (cee->reset_stats_pending == BFA_TRUE) {
+		cee->reset_stats_status = BFA_STATUS_FAILED;
+		cee->reset_stats_pending = BFA_FALSE;
+		if (cee->cbfn.reset_stats_cbfn) {
+			cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
+						   BFA_STATUS_FAILED);
+		}
+	}
+}
+
+/**
+ * bfa_cee_attach()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ *            ioc - Pointer to the ioc module data structure
+ *            dev - Pointer to the device driver module data structure
+ *                  The device driver specific mbox ISR functions have
+ *                  this pointer as one of the parameters.
+ *            trcmod -
+ *            logmod -
+ *
+ * @return void
+ */
+void
+bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
+	       struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
+{
+	bfa_assert(cee != NULL);
+	cee->dev = dev;
+	cee->trcmod = trcmod;
+	cee->logmod = logmod;
+	cee->ioc = ioc;
+
+	bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
+	bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
+	bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
+}
+
+/**
+ * bfa_cee_detach()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ *
+ * @return void
+ */
+void
+bfa_cee_detach(struct bfa_cee_s *cee)
+{
+	/*
+	 * For now, just check if there is some ioctl pending and mark that as
+	 * failed?
+	 */
+	/* bfa_cee_hbfail(cee); */
+}
diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_csdebug.c net-next-2.6-mod/drivers/net/bna/bfa_csdebug.c
--- net-next-2.6-orig/drivers/net/bna/bfa_csdebug.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_csdebug.c	2009-10-31 21:34:47.842536000 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#include <cs/bfa_debug.h>
+#include <bfa_os_inc.h>
+#include <cs/bfa_q.h>
+
+/**
+ *  cs_debug_api
+ */
+
+
+void
+bfa_panic(int line, char *file, char *panicstr)
+{
+	bfa_os_panic();
+}
+
+void
+bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
+{
+	bfa_os_panic();
+}
+
+int
+bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
+{
+	struct list_head        *tqe;
+
+	tqe = bfa_q_next(q);
+	while (tqe != q) {
+		if (tqe == qe)
+			return 1;
+		tqe = bfa_q_next(tqe);
+		if (tqe == NULL)
+			break;
+	}
+	return 0;
+}
+
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_ioc.c net-next-2.6-mod/drivers/net/bna/bfa_ioc.c
--- net-next-2.6-orig/drivers/net/bna/bfa_ioc.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_ioc.c	2009-10-31 21:34:47.850535000 -0700
@@ -0,0 +1,2273 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#include <bfa_ioc.h>
+#include <bfa_fwimg_priv.h>
+#include <cs/bfa_debug.h>
+#include <bfi/bfi_ioc.h>
+#include <bfi/bfi_ctreg.h>
+#include <defs/bfa_defs_pci.h>
+#include <cna.h>
+
+
+/**
+ * IOC local definitions
+ */
+#define BFA_IOC_TOV		2000	/* msecs */
+#define BFA_IOC_HB_TOV		1000	/* msecs */
+#define BFA_IOC_HB_FAIL_MAX	4
+#define BFA_IOC_HWINIT_MAX	2
+#define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
+#define BFA_IOC_TOV_RECOVER	(BFA_IOC_HB_FAIL_MAX * BFA_IOC_HB_TOV \
+				+ BFA_IOC_TOV)
+
+#define bfa_ioc_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
+			bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
+#define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
+
+#define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS)
+#define BFA_DBG_FWTRC_LEN					\
+	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\
+	 (sizeof(struct bfa_trc_mod_s) -			\
+	  BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
+#define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
+#define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
+
+#define BFA_FLASH_CHUNK_NO(off)         (off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_FLASH_OFFSET_IN_CHUNK(off)  (off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_FLASH_CHUNK_ADDR(chunkno)   (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
+bfa_boolean_t   bfa_auto_recover = BFA_FALSE;
+
+/*
+ * forward declarations
+ */
+static void     bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void     bfa_ioc_timeout(void *ioc);
+static void     bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void     bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_recover(struct bfa_ioc_s *ioc);
+static bfa_boolean_t bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+
+/**
+ *  bfa_ioc_sm
+ */
+
+/**
+ * IOC state machine events
+ */
+enum ioc_event {
+	IOC_E_ENABLE = 1,	/*  IOC enable request */
+	IOC_E_DISABLE = 2,	/*  IOC disable request */
+	IOC_E_TIMEOUT = 3,	/*  f/w response timeout */
+	IOC_E_FWREADY = 4,	/*  f/w initialization done */
+	IOC_E_FWRSP_GETATTR = 5,	/*  IOC get attribute response */
+	IOC_E_FWRSP_ENABLE = 6,	/*  enable f/w response */
+	IOC_E_FWRSP_DISABLE = 7,	/*  disable f/w response */
+	IOC_E_HBFAIL = 8,	/*  heartbeat failure */
+	IOC_E_HWERROR = 9,	/*  hardware error interrupt */
+	IOC_E_SEMLOCKED = 10,	/*  h/w semaphore is locked */
+	IOC_E_DETACH = 11,	/*  driver detach cleanup */
+};
+
+bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
+
+static struct bfa_sm_table_s ioc_sm_table[] = {
+	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
+	{BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
+	{BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
+	{BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
+	{BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
+	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
+	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
+	{BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
+	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+};
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
+{
+	ioc->retry_count = 0;
+	ioc->auto_recover = bfa_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_ENABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
+		break;
+
+	case IOC_E_DETACH:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_SEMLOCKED:
+		if (bfa_ioc_firmware_lock(ioc)) {
+			ioc->retry_count = 0;
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+		} else {
+			bfa_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
+		}
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
+		/*
+		 * fall through
+		 */
+
+	case IOC_E_DETACH:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	case IOC_E_FWREADY:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Notify enable completion callback and generate mismatch AEN.
+ */
+static void
+bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc)
+{
+	/**
+	 * Provide enable completion callback and AEN notification only once.
+	 */
+	if (ioc->retry_count == 0)
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	ioc->retry_count++;
+	bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
+		/*
+		 * fall through
+		 */
+
+	case IOC_E_DETACH:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	case IOC_E_FWREADY:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_SEMLOCKED:
+		ioc->retry_count = 0;
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_reset(ioc, BFA_FALSE);
+}
+
+/**
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_FWREADY:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/*
+		 * fall through
+		 */
+
+	case IOC_E_TIMEOUT:
+		ioc->retry_count++;
+		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_ioc_timer_start(ioc);
+			bfa_ioc_reset(ioc, BFA_TRUE);
+			break;
+		}
+
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_send_enable(ioc);
+}
+
+/**
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
+ */
+static void
+bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_FWRSP_ENABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/*
+		 * fall through
+		 */
+
+	case IOC_E_TIMEOUT:
+		ioc->retry_count++;
+		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
+				      BFI_IOC_UNINIT);
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+			break;
+		}
+
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_FWREADY:
+		bfa_ioc_send_enable(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_send_getattr(ioc);
+}
+
+/**
+ * IOC configuration in progress. Timer is active.
+ */
+static void
+bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_FWRSP_GETATTR:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/*
+		 * fall through
+		 */
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
+{
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
+	bfa_ioc_hb_monitor(ioc);
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_ENABLE:
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hb_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_HWERROR:
+	case IOC_E_FWREADY:
+		/**
+		 * Hard error or IOC recovery by other function.
+		 * Treat it same as heartbeat failure.
+		 */
+		bfa_ioc_hb_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOC_E_HBFAIL:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_send_disable(ioc);
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_HWERROR:
+	case IOC_E_FWRSP_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_ENABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		break;
+
+	case IOC_E_DISABLE:
+		ioc->cbfn->disable_cbfn(ioc->bfa);
+		break;
+
+	case IOC_E_FWREADY:
+		break;
+
+	case IOC_E_DETACH:
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
+{
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * Hardware initialization failed.
+ */
+static void
+bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+	case IOC_E_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_ioc_timer_stop(ioc);
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc)
+{
+	struct list_head *qe;
+	struct bfa_ioc_hbfail_notify_s *notify;
+
+	/**
+	 * Mark IOC as failed in hardware and stop firmware.
+	 */
+	bfa_ioc_lpu_stop(ioc);
+	bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_HBFAIL);
+
+	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
+		bfa_reg_write(ioc->ioc_regs.ll_halt, __FW_INIT_HALT_P);
+		/*
+		 * Wait for halt to take effect
+		 */
+		bfa_reg_read(ioc->ioc_regs.ll_halt);
+	}
+
+	/**
+	 * Notify driver and common modules registered for notification.
+	 */
+	ioc->cbfn->hbfail_cbfn(ioc->bfa);
+	list_for_each(qe, &ioc->hb_notify_q) {
+		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+		notify->cbfn(notify->cbarg);
+	}
+
+	/**
+	 * Flush any queued up mailbox requests.
+	 */
+	bfa_ioc_mbox_hbfail(ioc);
+
+	/**
+	 * Trigger auto-recovery after a delay.
+	 */
+	if (ioc->auto_recover) {
+		bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer,
+				bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER);
+	}
+}
+
+/**
+ * IOC heartbeat failure.
+ */
+static void
+bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+
+	switch (event) {
+
+	case IOC_E_ENABLE:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
+	case IOC_E_DISABLE:
+		if (ioc->auto_recover)
+			bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		break;
+
+	case IOC_E_FWREADY:
+		/**
+		 * Recovery is already initiated by other function.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+
+/**
+ *  bfa_ioc_pvt BFA IOC private functions
+ */
+
+static void
+bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+{
+	struct list_head *qe;
+	struct bfa_ioc_hbfail_notify_s *notify;
+
+	ioc->cbfn->disable_cbfn(ioc->bfa);
+
+	/**
+	 * Notify common modules registered for notification.
+	 */
+	list_for_each(qe, &ioc->hb_notify_q) {
+		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+		notify->cbfn(notify->cbarg);
+	}
+}
+
+static void
+bfa_ioc_sem_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+static void
+bfa_ioc_usage_sem_get(struct bfa_ioc_s *ioc)
+{
+	u32        r32;
+	int             cnt = 0;
+#define BFA_SEM_SPINCNT	1000
+
+	do {
+		r32 = bfa_reg_read(ioc->ioc_regs.ioc_usage_sem_reg);
+		cnt++;
+		if (cnt > BFA_SEM_SPINCNT)
+			break;
+	} while (r32 != 0);
+	bfa_assert(cnt < BFA_SEM_SPINCNT);
+}
+
+static void
+bfa_ioc_usage_sem_release(struct bfa_ioc_s *ioc)
+{
+	bfa_reg_write(ioc->ioc_regs.ioc_usage_sem_reg, 1);
+}
+
+static void
+bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
+{
+	u32        r32;
+
+	/**
+	 * First read to the semaphore register will return 0, subsequent reads
+	 * will return 1. Semaphore is released by writing 0 to the register
+	 */
+	r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
+	if (r32 == 0) {
+		bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+		return;
+	}
+
+	bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout,
+			ioc, BFA_IOC_TOV);
+}
+
+static void
+bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
+{
+	bfa_reg_write(ioc->ioc_regs.ioc_sem_reg, 1);
+}
+
+static void
+bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
+{
+	bfa_timer_stop(&ioc->sem_timer);
+}
+
+/**
+ * Initialize LPU local memory (aka secondary memory / SRAM)
+ */
+static void
+bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
+{
+	u32        pss_ctl;
+	int             i;
+#define PSS_LMEM_INIT_TIME  10000
+
+	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+	pss_ctl &= ~__PSS_LMEM_RESET;
+	pss_ctl |= __PSS_LMEM_INIT_EN;
+	pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */
+	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+
+	/**
+	 * wait for memory initialization to be complete
+	 */
+	i = 0;
+	do {
+		pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+		i++;
+	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
+
+	/**
+	 * If memory initialization is not successful, IOC timeout will catch
+	 * such failures.
+	 */
+	bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
+
+	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
+	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+}
+
+static void
+bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
+{
+	u32        pss_ctl;
+
+	/**
+	 * Take processor out of reset.
+	 */
+	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+	pss_ctl &= ~__PSS_LPU0_RESET;
+
+	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+}
+
+static void
+bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
+{
+	u32        pss_ctl;
+
+	/**
+	 * Put processors in reset.
+	 */
+	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
+
+	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+}
+
+/**
+ * Get driver and firmware versions.
+ */
+static void
+bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
+{
+	u32        pgnum, pgoff;
+	u32        loff = 0;
+	int             i;
+	u32       *fwsig = (u32 *) fwhdr;
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
+	     i++) {
+		fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		loff += sizeof(u32);
+	}
+}
+
+static u32 *
+bfa_ioc_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off)
+{
+	if (ioc->ctdev)
+		return bfi_image_ct_get_chunk(off);
+	return bfi_image_cb_get_chunk(off);
+}
+
+static          u32
+bfa_ioc_fwimg_get_size(struct bfa_ioc_s *ioc)
+{
+return (ioc->ctdev) ? bfi_image_ct_size : bfi_image_cb_size;
+}
+
+/**
+ * Returns TRUE if same.
+ */
+static          bfa_boolean_t
+bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
+{
+	struct bfi_ioc_image_hdr_s *drv_fwhdr;
+	int             i;
+
+	drv_fwhdr =
+		(struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0);
+
+	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
+		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
+			return BFA_FALSE;
+	}
+
+	return BFA_TRUE;
+}
+
+/**
+ * Return true if current running version is valid. Firmware signature and
+ * execution context (driver/bios) must match.
+ */
+static          bfa_boolean_t
+bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
+{
+	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
+
+	/**
+	 * If bios/efi boot (flash based) -- return true
+	 */
+	if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
+		return BFA_TRUE;
+
+	bfa_ioc_fwver_get(ioc, &fwhdr);
+	drv_fwhdr =
+		(struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0);
+
+	if (fwhdr.signature != drv_fwhdr->signature)
+		return BFA_FALSE;
+
+	if (fwhdr.exec != drv_fwhdr->exec)
+		return BFA_FALSE;
+
+	return bfa_ioc_fwver_cmp(ioc, &fwhdr);
+}
+
+/**
+ * Return true if firmware of current driver matches the running firmware.
+ */
+static          bfa_boolean_t
+bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc)
+{
+	enum bfi_ioc_state ioc_fwstate;
+	u32        usecnt;
+	struct bfi_ioc_image_hdr_s fwhdr;
+
+	/**
+	 * Firmware match check is relevant only for CNA.
+	 */
+	if (!ioc->cna)
+		return BFA_TRUE;
+
+	/**
+	 * If bios boot (flash based) -- do not increment usage count
+	 */
+	if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
+		return BFA_TRUE;
+
+	bfa_ioc_usage_sem_get(ioc);
+	usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg);
+
+	/**
+	 * If usage count is 0, always return TRUE.
+	 */
+	if (usecnt == 0) {
+		bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 1);
+		bfa_ioc_usage_sem_release(ioc);
+		return BFA_TRUE;
+	}
+
+	ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+
+	/**
+	 * Use count cannot be non-zero and chip in uninitialized state.
+	 */
+	bfa_assert(ioc_fwstate != BFI_IOC_UNINIT);
+
+	/**
+	 * Check if another driver with a different firmware is active
+	 */
+	bfa_ioc_fwver_get(ioc, &fwhdr);
+	if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
+		bfa_ioc_usage_sem_release(ioc);
+		return BFA_FALSE;
+	}
+
+	/**
+	 * Same firmware version. Increment the reference count.
+	 */
+	usecnt++;
+	bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt);
+	bfa_ioc_usage_sem_release(ioc);
+	return BFA_TRUE;
+}
+
+static void
+bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc)
+{
+	u32        usecnt;
+
+	/**
+	 * Firmware lock is relevant only for CNA.
+	 * If bios boot (flash based) -- do not decrement usage count
+	 */
+	if (!ioc->cna || (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ))
+		return;
+
+	/**
+	 * decrement usage count
+	 */
+	bfa_ioc_usage_sem_get(ioc);
+	usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg);
+	bfa_assert(usecnt > 0);
+
+	usecnt--;
+	bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt);
+
+	bfa_ioc_usage_sem_release(ioc);
+}
+
+/**
+ * Conditionally flush any pending message from firmware at start.
+ */
+static void
+bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
+{
+	u32        r32;
+
+	r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
+	if (r32)
+		bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1);
+}
+
+
+static void
+bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
+{
+	enum bfi_ioc_state ioc_fwstate;
+	bfa_boolean_t   fwvalid;
+
+	ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+
+	if (force)
+		ioc_fwstate = BFI_IOC_UNINIT;
+
+
+	/**
+	 * check if firmware is valid
+	 */
+	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
+			BFA_FALSE : bfa_ioc_fwver_valid(ioc);
+
+	if (!fwvalid) {
+		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+		return;
+	}
+
+	/**
+	 * If hardware initialization is in progress (initialized by other IOC),
+	 * just wait for an initialization completion interrupt.
+	 */
+	if (ioc_fwstate == BFI_IOC_INITING) {
+		ioc->cbfn->reset_cbfn(ioc->bfa);
+		return;
+	}
+
+	/**
+	 * If IOC function is disabled and firmware version is same,
+	 * just re-enable IOC.
+	 */
+	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
+
+		/**
+		 * When using MSI-X any pending firmware ready event should
+		 * be flushed. Otherwise MSI-X interrupts are not delivered.
+		 */
+		bfa_ioc_msgflush(ioc);
+		ioc->cbfn->reset_cbfn(ioc->bfa);
+		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		return;
+	}
+
+	/**
+	 * Initialize the h/w for any other states.
+	 */
+	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+}
+
+static void
+bfa_ioc_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+
+	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
+}
+
+void
+bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
+{
+	u32       *msgp = (u32 *) ioc_msg;
+	u32        i;
+
+
+	bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
+
+	/*
+	 * first write msg to mailbox registers
+	 */
+	for (i = 0; i < len / sizeof(u32); i++)
+		bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32),
+			      bfa_os_wtole(msgp[i]));
+
+	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
+		bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32), 0);
+
+	/*
+	 * write 1 to mailbox CMD to trigger LPU event
+	 */
+	bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1);
+	(void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+}
+
+static void
+bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
+{
+	struct bfi_ioc_ctrl_req_s enable_req;
+
+	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
+		    bfa_ioc_portid(ioc));
+	enable_req.ioc_class = ioc->ioc_mc;
+	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
+}
+
+static void
+bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
+{
+	struct bfi_ioc_ctrl_req_s disable_req;
+
+	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
+		    bfa_ioc_portid(ioc));
+	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
+}
+
+static void
+bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
+{
+	struct bfi_ioc_getattr_req_s attr_req;
+
+	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
+		    bfa_ioc_portid(ioc));
+	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
+	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
+}
+
+static void
+bfa_ioc_hb_check(void *cbarg)
+{
+	struct bfa_ioc_s *ioc = cbarg;
+	u32        hb_count;
+
+	hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
+	if (ioc->hb_count == hb_count) {
+		ioc->hb_fail++;
+	} else {
+		ioc->hb_count = hb_count;
+		ioc->hb_fail = 0;
+	}
+
+	if (ioc->hb_fail >= BFA_IOC_HB_FAIL_MAX) {
+		ioc->hb_fail = 0;
+		bfa_ioc_recover(ioc);
+		return;
+	}
+
+	bfa_ioc_mbox_poll(ioc);
+	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
+			BFA_IOC_HB_TOV);
+}
+
+static void
+bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
+{
+	ioc->hb_fail = 0;
+	ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
+	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
+			BFA_IOC_HB_TOV);
+}
+
+static void
+bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
+{
+	bfa_timer_stop(&ioc->ioc_timer);
+}
+
+/**
+ * Host to LPU mailbox message addresses
+ */
+static struct {
+	u32        hfn_mbox, lpu_mbox, hfn_pgn;
+} iocreg_fnreg[] = {
+	{
+	HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0}, {
+	HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1}, {
+	HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2}, {
+	HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3}
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 0
+ */
+static struct {
+	u32        hfn, lpu;
+} iocreg_mbcmd_p0[] = {
+	{
+	HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT}, {
+	HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT}, {
+	HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT}, {
+	HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT}
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 1
+ */
+static struct {
+	u32        hfn, lpu;
+} iocreg_mbcmd_p1[] = {
+	{
+	HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT}, {
+	HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT}, {
+	HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT}, {
+	HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT}
+};
+
+/**
+ * Shared IRQ handling in INTX mode
+ */
+static struct {
+	u32        isr, msk;
+} iocreg_shirq_next[] = {
+	{
+	HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK}, {
+	HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK}, {
+	HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK}, {
+HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK},};
+
+static void
+bfa_ioc_reg_init(struct bfa_ioc_s *ioc)
+{
+	bfa_os_addr_t   rb;
+	int             pcifn = bfa_ioc_pcifn(ioc);
+
+	rb = bfa_ioc_bar0(ioc);
+
+	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
+	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
+	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+
+	if (ioc->port_id == 0) {
+		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
+		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
+		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+	} else {
+		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
+		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
+		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+	}
+
+	/**
+	 * Shared IRQ handling in INTX mode
+	 */
+	ioc->ioc_regs.shirq_isr_next = rb + iocreg_shirq_next[pcifn].isr;
+	ioc->ioc_regs.shirq_msk_next = rb + iocreg_shirq_next[pcifn].msk;
+
+	/*
+	 * PSS control registers
+	 */
+	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
+	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
+	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
+
+	/*
+	 * IOC semaphore registers and serialization
+	 */
+	ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
+	ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
+	ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+
+	/**
+	 * sram memory access
+	 */
+	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
+	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
+	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT)
+		ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+}
+
+/**
+ *      Initiate a full firmware download.
+ */
+static void
+bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
+		    u32 boot_param)
+{
+	u32       *fwimg;
+	u32        pgnum, pgoff;
+	u32        loff = 0;
+	u32        chunkno = 0;
+	u32        i;
+
+	/**
+	 * Initialize LMEM first before code download
+	 */
+	bfa_ioc_lmem_init(ioc);
+
+	/**
+	 * Flash based firmware boot
+	 */
+	if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
+		boot_type = BFI_BOOT_TYPE_FLASH;
+	fwimg = bfa_ioc_fwimg_get_chunk(ioc, chunkno);
+	fwimg[BFI_BOOT_TYPE_OFF / sizeof(u32)] = bfa_os_swap32(boot_type);
+	fwimg[BFI_BOOT_PARAM_OFF / sizeof(u32)] =
+		bfa_os_swap32(boot_param);
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	for (i = 0; i < bfa_ioc_fwimg_get_size(ioc); i++) {
+
+		if (BFA_FLASH_CHUNK_NO(i) != chunkno) {
+			chunkno = BFA_FLASH_CHUNK_NO(i);
+			fwimg = bfa_ioc_fwimg_get_chunk(ioc,
+					BFA_FLASH_CHUNK_ADDR(chunkno));
+		}
+
+		/**
+		 * write smem
+		 */
+		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
+			      fwimg[BFA_FLASH_OFFSET_IN_CHUNK(i)]);
+
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+		}
+	}
+
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+		      bfa_ioc_smem_pgnum(ioc, 0));
+}
+
+static void
+bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
+{
+	bfa_ioc_hwinit(ioc, force);
+}
+
+/**
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
+{
+	struct bfi_ioc_attr_s *attr = ioc->attr;
+
+	attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
+	attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
+
+	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
+}
+
+/**
+ * Attach time initialization of mbox logic.
+ */
+static void
+bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	int             mc;
+
+	INIT_LIST_HEAD(&mod->cmd_q);
+	for (mc = 0; mc < BFI_MC_MAX; mc++) {
+		mod->mbhdlr[mc].cbfn = NULL;
+		mod->mbhdlr[mc].cbarg = ioc->bfa;
+	}
+}
+
+/**
+ * Mbox poll timer -- restarts any pending mailbox requests.
+ */
+static void
+bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd_s *cmd;
+	u32        stat;
+
+	/**
+	 * If no command pending, do nothing
+	 */
+	if (list_empty(&mod->cmd_q))
+		return;
+
+	/**
+	 * If previous command is not yet fetched by firmware, do nothing
+	 */
+	stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+	if (stat)
+		return;
+
+	/**
+	 * Enqueue command to firmware.
+	 */
+	bfa_q_deq(&mod->cmd_q, &cmd);
+	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Cleanup any pending requests.
+ */
+static void
+bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd_s *cmd;
+
+	while (!list_empty(&mod->cmd_q))
+		bfa_q_deq(&mod->cmd_q, &cmd);
+}
+
+/**
+ * Initialize IOC to port mapping.
+ */
+
+#define FNC_PERS_FN_SHIFT(__fn)	((__fn) * 8)
+static void
+bfa_ioc_map_port(struct bfa_ioc_s *ioc)
+{
+	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+	u32        r32;
+
+	/**
+	 * For crossbow, port id is same as pci function.
+	 */
+	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT) {
+		ioc->port_id = bfa_ioc_pcifn(ioc);
+		return;
+	}
+
+	/**
+	 * For catapult, base port id on personality register and IOC type
+	 */
+	r32 = bfa_reg_read(rb + FNC_PERS_REG);
+	r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
+	ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
+
+}
+
+
+
+/**
+ *  bfa_ioc_public
+ */
+
+/**
+* Set interrupt mode for a function: INTX or MSIX
+ */
+void
+bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
+{
+	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+	u32        r32, mode;
+
+	r32 = bfa_reg_read(rb + FNC_PERS_REG);
+
+	mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
+		__F0_INTX_STATUS;
+
+	/**
+	 * If already in desired mode, do not change anything
+	 */
+	if (!msix && mode)
+		return;
+
+	if (msix)
+		mode = __F0_INTX_STATUS_MSIX;
+	else
+		mode = __F0_INTX_STATUS_INTA;
+
+	r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+	r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+
+	bfa_reg_write(rb + FNC_PERS_REG, r32);
+}
+
+bfa_status_t
+bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
+{
+	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+	u32        pll_sclk, pll_fclk, r32;
+
+	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
+		pll_sclk =
+			__APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN |
+			__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(0U) |
+			__APP_PLL_312_JITLMT0_1(3U) |
+			__APP_PLL_312_CNTLMT0_1(1U);
+		pll_fclk =
+			__APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN |
+			__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(0U) |
+			__APP_PLL_425_JITLMT0_1(3U) |
+			__APP_PLL_425_CNTLMT0_1(1U);
+
+		/**
+		 * 	For catapult, choose operational mode FC/FCoE
+		 */
+		if (ioc->fcmode) {
+			bfa_reg_write((rb + OP_MODE), 0);
+			bfa_reg_write((rb + ETH_MAC_SER_REG),
+				      __APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2
+				      | __APP_EMS_CHANNEL_SEL);
+		} else {
+			ioc->pllinit = BFA_TRUE;
+			bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
+			bfa_reg_write((rb + ETH_MAC_SER_REG),
+				      __APP_EMS_REFCKBUFEN1);
+		}
+	} else {
+		pll_sclk =
+			__APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN |
+			__APP_PLL_312_P0_1(3U) | __APP_PLL_312_JITLMT0_1(3U) |
+			__APP_PLL_312_CNTLMT0_1(3U);
+		pll_fclk =
+			__APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN |
+			__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
+			__APP_PLL_425_JITLMT0_1(3U) |
+			__APP_PLL_425_CNTLMT0_1(3U);
+	}
+
+	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
+
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+
+	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+		      __APP_PLL_312_LOGIC_SOFT_RESET);
+	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+		      __APP_PLL_312_BYPASS | __APP_PLL_312_LOGIC_SOFT_RESET);
+	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+		      __APP_PLL_425_LOGIC_SOFT_RESET);
+	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+		      __APP_PLL_425_BYPASS | __APP_PLL_425_LOGIC_SOFT_RESET);
+	bfa_os_udelay(2);
+	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+		      __APP_PLL_312_LOGIC_SOFT_RESET);
+	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+		      __APP_PLL_425_LOGIC_SOFT_RESET);
+
+	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+		      pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET);
+	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+		      pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET);
+
+	/**
+	 * Wait for PLLs to lock.
+	 */
+	bfa_os_udelay(2000);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+
+	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
+	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
+
+	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
+		bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
+		bfa_os_udelay(1000);
+		r32 = bfa_reg_read((rb + MBIST_STAT_REG));
+	}
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Interface used by diag module to do firmware boot with memory test
+ * as the entry vector.
+ */
+void
+bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
+{
+	bfa_os_addr_t   rb;
+
+	bfa_ioc_stats(ioc, ioc_boots);
+
+	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
+		return;
+
+	/**
+	 * Initialize IOC state of all functions on a chip reset.
+	 */
+	rb = ioc->pcidev.pci_bar_kva;
+	if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+		bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST);
+		bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST);
+	} else {
+		bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_INITING);
+		bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_INITING);
+	}
+
+	bfa_ioc_download_fw(ioc, boot_type, boot_param);
+
+	/**
+	 * Enable interrupts just before starting LPU
+	 */
+	ioc->cbfn->reset_cbfn(ioc->bfa);
+	bfa_ioc_lpu_start(ioc);
+}
+
+/**
+ * Enable/disable IOC failure auto recovery.
+ */
+void
+bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
+{
+	bfa_auto_recover = BFA_FALSE;
+}
+
+
+bfa_boolean_t
+bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
+{
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
+}
+
+void
+bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
+{
+	u32       *msgp = mbmsg;
+	u32        r32;
+	int             i;
+
+	/**
+	 * read the MBOX msg
+	 */
+	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
+	     i++) {
+		r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox +
+				   i * sizeof(u32));
+		msgp[i] = bfa_os_htonl(r32);
+	}
+
+	/**
+	 * turn off mailbox interrupt by clearing mailbox status
+	 */
+	bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1);
+	bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
+}
+
+void
+bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
+{
+	union bfi_ioc_i2h_msg_u *msg;
+
+	msg = (union bfi_ioc_i2h_msg_u *)m;
+
+	bfa_ioc_stats(ioc, ioc_isrs);
+
+	switch (msg->mh.msg_id) {
+	case BFI_IOC_I2H_HBEAT:
+		break;
+
+	case BFI_IOC_I2H_READY_EVENT:
+		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		break;
+
+	case BFI_IOC_I2H_ENABLE_REPLY:
+		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+		break;
+
+	case BFI_IOC_I2H_DISABLE_REPLY:
+		bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+		break;
+
+	case BFI_IOC_I2H_GETATTR_REPLY:
+		bfa_ioc_getattr_reply(ioc);
+		break;
+
+	default:
+		bfa_assert(0);
+	}
+}
+
+/**
+ * IOC attach time initialization and setup.
+ *
+ * @param[in]	ioc	memory for IOC
+ * @param[in]	bfa	driver instance structure
+ * @param[in]	trcmod	kernel trace module
+ * @param[in]	aen	kernel aen event module
+ * @param[in]	logm	kernel logging module
+ */
+void
+bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
+	       struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod,
+	       struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
+{
+	ioc->bfa = bfa;
+	ioc->cbfn = cbfn;
+	ioc->timer_mod = timer_mod;
+	ioc->trcmod = trcmod;
+	ioc->aen = aen;
+	ioc->logm = logm;
+	ioc->fcmode = BFA_FALSE;
+	ioc->pllinit = BFA_FALSE;
+	ioc->dbg_fwsave_once = BFA_TRUE;
+
+	bfa_ioc_mbox_attach(ioc);
+	INIT_LIST_HEAD(&ioc->hb_notify_q);
+
+	bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+}
+
+/**
+ * Driver detach time IOC cleanup.
+ */
+void
+bfa_ioc_detach(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_DETACH);
+}
+
+/**
+ * Setup IOC PCI properties.
+ *
+ * @param[in]	pcidev	PCI device information for this IOC
+ */
+void
+bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
+		 enum bfi_mclass mc)
+{
+	ioc->ioc_mc = mc;
+	ioc->pcidev = *pcidev;
+	ioc->ctdev = (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT);
+	ioc->cna = ioc->ctdev && !ioc->fcmode;
+
+	bfa_ioc_map_port(ioc);
+	bfa_ioc_reg_init(ioc);
+}
+
+/**
+ * Initialize IOC dma memory
+ *
+ * @param[in]	dm_kva	kernel virtual address of IOC dma memory
+ * @param[in]	dm_pa	physical address of IOC dma memory
+ */
+void
+bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
+{
+	/**
+	 * dma memory for firmware attribute
+	 */
+	ioc->attr_dma.kva = dm_kva;
+	ioc->attr_dma.pa = dm_pa;
+	ioc->attr = (struct bfi_ioc_attr_s *)dm_kva;
+}
+
+/**
+ * Return size of dma memory required.
+ */
+u32
+bfa_ioc_meminfo(void)
+{
+	return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_ioc_enable(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_stats(ioc, ioc_enables);
+	ioc->dbg_fwsave_once = BFA_TRUE;
+
+	bfa_fsm_send_event(ioc, IOC_E_ENABLE);
+}
+
+void
+bfa_ioc_disable(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_stats(ioc, ioc_disables);
+	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
+}
+
+/**
+ * Returns memory required for saving firmware trace in case of crash.
+ * Driver must call this interface to allocate memory required for
+ * automatic saving of firmware trace. Driver should call
+ * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this
+ * trace memory.
+ */
+int
+bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
+{
+return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+}
+
+/**
+ * Initialize memory for saving firmware trace. Driver must initialize
+ * trace memory before call bfa_ioc_enable().
+ */
+void
+bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
+{
+	bfa_assert(ioc->auto_recover);
+	ioc->dbg_fwsave = dbg_fwsave;
+	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover);
+}
+
+u32
+bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr)
+{
+	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
+}
+
+u32
+bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
+{
+	return PSS_SMEM_PGOFF(fmaddr);
+}
+
+/**
+ * Register mailbox message handler functions
+ *
+ * @param[in]	ioc		IOC instance
+ * @param[in]	mcfuncs		message class handler functions
+ */
+void
+bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	int             mc;
+
+	for (mc = 0; mc < BFI_MC_MAX; mc++)
+		mod->mbhdlr[mc].cbfn = mcfuncs[mc];
+}
+
+/**
+ * Register mailbox message handler function, to be called by common modules
+ */
+void
+bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
+		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+
+	mod->mbhdlr[mc].cbfn = cbfn;
+	mod->mbhdlr[mc].cbarg = cbarg;
+}
+
+/**
+ * Queue a mailbox command request to firmware. Waits if mailbox is busy.
+ * Responsibility of caller to serialize
+ *
+ * @param[in]	ioc	IOC instance
+ * @param[i]	cmd	Mailbox command
+ */
+void
+bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	u32        stat;
+
+	/**
+	 * If a previous command is pending, queue new command
+	 */
+	if (!list_empty(&mod->cmd_q)) {
+		list_add_tail(&cmd->qe, &mod->cmd_q);
+		return;
+	}
+
+	/**
+	 * If mailbox is busy, queue command for poll timer
+	 */
+	stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+	if (stat) {
+		list_add_tail(&cmd->qe, &mod->cmd_q);
+		return;
+	}
+
+	/**
+	 * mailbox is free -- queue command to firmware
+	 */
+	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Handle mailbox interrupts
+ */
+void
+bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
+{
+	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	struct bfi_mbmsg_s m;
+	int             mc;
+
+	bfa_ioc_msgget(ioc, &m);
+
+	/**
+	 * Treat IOC message class as special.
+	 */
+	mc = m.mh.msg_class;
+	if (mc == BFI_MC_IOC) {
+		bfa_ioc_isr(ioc, &m);
+		return;
+	}
+
+	if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+		return;
+
+	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+}
+
+void
+bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
+}
+
+#ifndef BFA_BIOS_BUILD
+
+/**
+ * return true if IOC is disabled
+ */
+bfa_boolean_t
+bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
+{
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
+		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
+}
+
+/**
+ * return true if IOC firmware is different.
+ */
+bfa_boolean_t
+bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
+{
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
+		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
+		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
+}
+
+#define bfa_ioc_state_disabled(__sm)		\
+	(((__sm) == BFI_IOC_UNINIT) ||		\
+	 ((__sm) == BFI_IOC_INITING) ||		\
+	 ((__sm) == BFI_IOC_HWINIT) ||		\
+	 ((__sm) == BFI_IOC_DISABLED) ||	\
+	 ((__sm) == BFI_IOC_HBFAIL) ||		\
+	 ((__sm) == BFI_IOC_CFG_DISABLED))
+
+/**
+ * Check if adapter is disabled -- both IOCs should be in a disabled
+ * state.
+ */
+bfa_boolean_t
+bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
+{
+	u32        ioc_state;
+	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+
+	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
+		return BFA_FALSE;
+
+	ioc_state = bfa_reg_read(rb + BFA_IOC0_STATE_REG);
+	if (!bfa_ioc_state_disabled(ioc_state))
+		return BFA_FALSE;
+
+	ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
+	if (!bfa_ioc_state_disabled(ioc_state))
+		return BFA_FALSE;
+
+	return BFA_TRUE;
+}
+
+/**
+ * Add to IOC heartbeat failure notification queue. To be used by common
+ * modules such as
+ */
+void
+bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
+			struct bfa_ioc_hbfail_notify_s *notify)
+{
+	list_add_tail(&notify->qe, &ioc->hb_notify_q);
+}
+
+#define BFA_MFG_NAME "Brocade"
+void
+bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
+			 struct bfa_adapter_attr_s *ad_attr)
+{
+	struct bfi_ioc_attr_s *ioc_attr;
+	char            model[BFA_ADAPTER_MODEL_NAME_LEN];
+
+	ioc_attr = ioc->attr;
+	bfa_os_memcpy((void *)&ad_attr->serial_num,
+		      (void *)ioc_attr->brcd_serialnum,
+		      BFA_ADAPTER_SERIAL_NUM_LEN);
+
+	bfa_os_memcpy(&ad_attr->fw_ver, ioc_attr->fw_version, BFA_VERSION_LEN);
+	bfa_os_memcpy(&ad_attr->optrom_ver, ioc_attr->optrom_version,
+		      BFA_VERSION_LEN);
+	bfa_os_memcpy(&ad_attr->manufacturer, BFA_MFG_NAME,
+		      BFA_ADAPTER_MFG_NAME_LEN);
+	bfa_os_memcpy(&ad_attr->vpd, &ioc_attr->vpd,
+		      sizeof(struct bfa_mfg_vpd_s));
+
+	ad_attr->nports = BFI_ADAPTER_GETP(NPORTS, ioc_attr->adapter_prop);
+	ad_attr->max_speed = BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop);
+
+	/**
+	 * model name
+	 */
+	if (BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop) == 10) {
+		strcpy(model, "BR-10?0");
+		model[5] = '0' + ad_attr->nports;
+	} else {
+		strcpy(model, "Brocade-??5");
+		model[8] =
+			'0' + BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop);
+		model[9] = '0' + ad_attr->nports;
+	}
+
+	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
+		ad_attr->prototype = 1;
+	else
+		ad_attr->prototype = 0;
+
+	bfa_os_memcpy(&ad_attr->model, model, BFA_ADAPTER_MODEL_NAME_LEN);
+	bfa_os_memcpy(&ad_attr->model_descr, &ad_attr->model,
+		      BFA_ADAPTER_MODEL_NAME_LEN);
+
+	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
+	ad_attr->mac = bfa_ioc_get_mac(ioc);
+
+	ad_attr->pcie_gen = ioc_attr->pcie_gen;
+	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
+	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
+	ad_attr->asic_rev = ioc_attr->asic_rev;
+	ad_attr->hw_ver[0] = 'R';
+	ad_attr->hw_ver[1] = 'e';
+	ad_attr->hw_ver[2] = 'v';
+	ad_attr->hw_ver[3] = '-';
+	ad_attr->hw_ver[4] = ioc_attr->asic_rev;
+	ad_attr->hw_ver[5] = '\0';
+
+	ad_attr->cna_capable = ioc->cna;
+}
+
+void
+bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
+{
+	bfa_os_memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
+
+	ioc_attr->state = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+	ioc_attr->port_id = ioc->port_id;
+
+	if (!ioc->ctdev)
+		ioc_attr->ioc_type = BFA_IOC_TYPE_FC;
+	else if (ioc->ioc_mc == BFI_MC_IOCFC)
+		ioc_attr->ioc_type = BFA_IOC_TYPE_FCoE;
+	else if (ioc->ioc_mc == BFI_MC_LL)
+		ioc_attr->ioc_type = BFA_IOC_TYPE_LL;
+
+	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
+
+	ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
+	ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+	ioc_attr->pci_attr.chip_rev[0] = 'R';
+	ioc_attr->pci_attr.chip_rev[1] = 'e';
+	ioc_attr->pci_attr.chip_rev[2] = 'v';
+	ioc_attr->pci_attr.chip_rev[3] = '-';
+	ioc_attr->pci_attr.chip_rev[4] = ioc_attr->adapter_attr.asic_rev;
+	ioc_attr->pci_attr.chip_rev[5] = '\0';
+}
+
+/**
+ *  hal_wwn_public
+ */
+wwn_t
+bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
+{
+	union {
+		wwn_t           wwn;
+		u8         byte[sizeof(wwn_t)];
+	}
+	w;
+
+	w.wwn = ioc->attr->mfg_wwn;
+
+	if (bfa_ioc_portid(ioc) == 1)
+		w.byte[7]++;
+
+	return w.wwn;
+}
+
+wwn_t
+bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc)
+{
+	union {
+		wwn_t           wwn;
+		u8         byte[sizeof(wwn_t)];
+	}
+	w;
+
+	w.wwn = ioc->attr->mfg_wwn;
+
+	if (bfa_ioc_portid(ioc) == 1)
+		w.byte[7]++;
+
+	w.byte[0] = 0x20;
+
+	return w.wwn;
+}
+
+wwn_t
+bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst)
+{
+	union {
+		wwn_t           wwn;
+		u8         byte[sizeof(wwn_t)];
+	}
+	w              , w5;
+
+
+	w.wwn = ioc->attr->mfg_wwn;
+	w5.byte[0] = 0x50 | w.byte[2] >> 4;
+	w5.byte[1] = w.byte[2] << 4 | w.byte[3] >> 4;
+	w5.byte[2] = w.byte[3] << 4 | w.byte[4] >> 4;
+	w5.byte[3] = w.byte[4] << 4 | w.byte[5] >> 4;
+	w5.byte[4] = w.byte[5] << 4 | w.byte[6] >> 4;
+	w5.byte[5] = w.byte[6] << 4 | w.byte[7] >> 4;
+	w5.byte[6] = w.byte[7] << 4 | (inst & 0x0f00) >> 8;
+	w5.byte[7] = (inst & 0xff);
+
+	return w5.wwn;
+}
+
+u64
+bfa_ioc_get_adid(struct bfa_ioc_s *ioc)
+{
+	return ioc->attr->mfg_wwn;
+}
+
+mac_t
+bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
+{
+	mac_t           mac;
+
+	mac = ioc->attr->mfg_mac;
+	mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+
+	return mac;
+}
+
+void
+bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
+{
+	ioc->fcmode = BFA_TRUE;
+	ioc->port_id = bfa_ioc_pcifn(ioc);
+}
+
+bfa_boolean_t
+bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
+{
+	return ioc->fcmode || (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT);
+}
+
+/**
+ * Return true if interrupt should be claimed.
+ */
+bfa_boolean_t
+bfa_ioc_intx_claim(struct bfa_ioc_s *ioc)
+{
+	u32        isr, msk;
+
+	/**
+	 * Always claim if not catapult.
+	 */
+	if (!ioc->ctdev)
+		return BFA_TRUE;
+
+	/**
+	 * FALSE if next device is claiming interrupt.
+	 * TRUE if next device is not interrupting or not present.
+	 */
+	msk = bfa_reg_read(ioc->ioc_regs.shirq_msk_next);
+	isr = bfa_reg_read(ioc->ioc_regs.shirq_isr_next);
+	return !(isr & ~msk);
+}
+
+/**
+ * Retrieve saved firmware trace from a prior IOC failure.
+ */
+bfa_status_t
+bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
+{
+	int             tlen;
+
+	if (ioc->dbg_fwsave_len == 0)
+		return BFA_STATUS_ENOFSAVE;
+
+	tlen = *trclen;
+	if (tlen > ioc->dbg_fwsave_len)
+		tlen = ioc->dbg_fwsave_len;
+
+	bfa_os_memcpy(trcdata, ioc->dbg_fwsave, tlen);
+	*trclen = tlen;
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Retrieve saved firmware trace from a prior IOC failure.
+ */
+bfa_status_t
+bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
+{
+	u32        pgnum;
+	u32        loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
+	int             i, tlen;
+	u32       *tbuf = trcdata, r32;
+
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+	loff = bfa_ioc_smem_pgoff(ioc, loff);
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	tlen = *trclen;
+	if (tlen > BFA_DBG_FWTRC_LEN)
+		tlen = BFA_DBG_FWTRC_LEN;
+	tlen /= sizeof(u32);
+
+
+	for (i = 0; i < tlen; i++) {
+		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		tbuf[i] = bfa_os_ntohl(r32);
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+		}
+	}
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+		      bfa_ioc_smem_pgnum(ioc, 0));
+
+	*trclen = tlen * sizeof(u32);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Save firmware trace if configured.
+ */
+static void
+bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
+{
+	int             tlen;
+
+	if (ioc->dbg_fwsave_len) {
+		tlen = ioc->dbg_fwsave_len;
+		bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
+	}
+}
+
+/**
+ * Firmware failure detected. Start recovery actions.
+ */
+static void
+bfa_ioc_recover(struct bfa_ioc_s *ioc)
+{
+	if (ioc->dbg_fwsave_once) {
+		ioc->dbg_fwsave_once = BFA_FALSE;
+		bfa_ioc_debug_save(ioc);
+	}
+
+	bfa_ioc_stats(ioc, ioc_hbfails);
+	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
+}
+
+#else
+
+static void
+bfa_ioc_recover(struct bfa_ioc_s *ioc)
+{
+	bfa_assert(0);
+}
+
+#endif
+
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_sm.c net-next-2.6-mod/drivers/net/bna/bfa_sm.c
--- net-next-2.6-orig/drivers/net/bna/bfa_sm.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_sm.c	2009-10-31 21:34:47.858534000 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ *  bfasm.c BFA State machine utility functions
+ */
+
+#include <cs/bfa_sm.h>
+
+/**
+ *  cs_sm_api
+ */
+
+int
+bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
+{
+	int             i = 0;
+
+	while (smt[i].sm && smt[i].sm != sm)
+		i++;
+	return smt[i].state;
+}
+
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_if.c net-next-2.6-mod/drivers/net/bna/bna_if.c
--- net-next-2.6-orig/drivers/net/bna/bna_if.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_if.c	2009-10-31 21:34:47.865537000 -0700
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ *	Copyright (c) 2007-2008 Brocade Communications Systems, Inc.
+ *	All rights reserved.
+ *
+ *	file bna_if.c BNA Hardware and Firmware Interface
+ */
+#include <bna_os.h>
+#include "bna.h"
+#include "bna_hwreg.h"
+#include "bna_priv.h"
+#include "bna_iocll.h"
+#include "bna_intr.h"
+#include <bfi/bfi_cee.h>
+#include <protocol/types.h>
+#include <cee/bfa_cee.h>
+
+
+
+
+#define BNA_FLASH_DMA_BUF_SZ	0x010000	/* 64K */
+
+#define DO_CALLBACK(cbfn)	\
+do {				\
+	if (mb_cbfns->cbfn) {      \
+		if (qe && qe->cbarg) {      \
+			(mb_cbfns->cbfn)(qe->cbarg, status);      \
+		} else {					\
+			(mb_cbfns->cbfn)(dev->cbarg, status);      \
+		}			\
+	}			\
+} while (0)
+
+#define DO_DIAG_CALLBACK(cbfn, data)	\
+do {								\
+	if (mb_cbfns->cbfn) {      \
+		if (qe && qe->cbarg) {      \
+			(mb_cbfns->cbfn)(qe->cbarg, data, status);      \
+		} else {					\
+			(mb_cbfns->cbfn)(dev->cbarg, data, status);      \
+		}						\
+	}							\
+} while (0)
+
+#define bna_mbox_q_is_empty(mb_q)		\
+	((mb_q)->producer_index == 		\
+	    (mb_q)->consumer_index)
+
+#define bna_mbox_q_first(mb_q)			\
+	 (&(mb_q)->mb_qe[(mb_q)->consumer_index])
+
+/* FIXME : Should come from the driver */
+static u32 bna_ioc_auto_recover;
+
+/**
+ * bna_register_callback()
+ *
+ *	  Function called by the driver to register a callback
+ *	  with the BNA
+ *
+ * @param[in] bna_dev   - Opaque handle to BNA private device
+ * @param[in] cbfns	- Structure for the callback functions.
+ * @param[in] cbarg	- Argument to use with the callback
+ * @param[in] cmd_code  - Command code exported to the drivers
+ *
+ * @return void
+ */
+void bna_register_callback(struct bna_dev_s *dev, struct bna_mbox_cbfn *cbfns,
+	void *cbarg)
+{
+	bna_os_memcpy(&dev->mb_cbfns, cbfns, sizeof(dev->mb_cbfns));
+	dev->cbarg = cbarg;
+}
+
+void
+bna_mbox_q_init(struct bna_mbox_q *q)
+{
+	BNA_ASSERT(BNA_POWER_OF_2(BNA_MAX_MBOX_CMD_QUEUE));
+
+	q->producer_index = q->consumer_index = 0;
+	q->posted = NULL;
+}
+
+static struct bna_mbox_cmd_qe *
+bna_mbox_enq(struct bna_mbox_q *mbox_q,
+	void *cmd, u32 cmd_len, void *cbarg) {
+	struct bna_mbox_cmd_qe *qe;
+
+	if (!BNA_QE_FREE_CNT(mbox_q, BNA_MAX_MBOX_CMD_QUEUE)) {
+		DPRINTK(WARNING, "No free Mbox Command Element\n");
+		return NULL;
+	}
+
+	DPRINTK(DEBUG, "Mbox PI 0x%x\n", mbox_q->producer_index);
+
+	qe = &mbox_q->mb_qe[mbox_q->producer_index];
+	BNA_QE_INDX_ADD(mbox_q->producer_index, 1,
+	    BNA_MAX_MBOX_CMD_QUEUE);
+	bna_os_memcpy(&qe->cmd.msg[0], cmd, cmd_len);
+	qe->cmd_len = cmd_len;
+	qe->cbarg = cbarg;
+
+	return qe;
+}
+
+static void
+bna_mbox_deq(struct bna_mbox_q *mbox_q)
+{
+
+	DPRINTK(DEBUG, "Mbox CI 0x%x\n", mbox_q->consumer_index);
+
+	/* Free one from the head */
+	BNA_QE_INDX_ADD(mbox_q->consumer_index, 1,
+	    BNA_MAX_MBOX_CMD_QUEUE);
+}
+
+static void
+bna_do_stats_update(struct bna_dev_s *dev, u8 status)
+{
+	if (status != BFI_LL_CMD_OK)
+		return;
+	bna_stats_process(dev);
+}
+
+static void
+bna_do_drv_ll_cb(struct bna_dev_s *dev, u8 cmd_code,
+   u8 status, struct bna_mbox_cmd_qe *qe)
+{
+	struct bna_mbox_cbfn *mb_cbfns = &dev->mb_cbfns;
+
+	switch (cmd_code) {
+	case BFI_LL_I2H_MAC_UCAST_SET_RSP:
+		DO_CALLBACK(ucast_set_cb);
+		break;
+	case BFI_LL_I2H_MAC_UCAST_ADD_RSP:
+		DO_CALLBACK(ucast_add_cb);
+		break;
+	case BFI_LL_I2H_MAC_UCAST_DEL_RSP:
+		DO_CALLBACK(ucast_del_cb);
+		break;
+	case BFI_LL_I2H_MAC_MCAST_ADD_RSP:
+		DO_CALLBACK(mcast_add_cb);
+		break;
+	case BFI_LL_I2H_MAC_MCAST_DEL_RSP:
+		DO_CALLBACK(mcast_del_cb);
+		break;
+	case BFI_LL_I2H_MAC_MCAST_FILTER_RSP:
+		DO_CALLBACK(mcast_filter_cb);
+		break;
+	case BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP:
+		DO_CALLBACK(mcast_del_all_cb);
+		break;
+	case BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP:
+		DO_CALLBACK(set_promisc_cb);
+		break;
+	case BFI_LL_I2H_RXF_DEFAULT_SET_RSP:
+		DO_CALLBACK(set_default_cb);
+		break;
+	case BFI_LL_I2H_TXQ_STOP_RSP:
+		DO_CALLBACK(txq_stop_cb);
+		break;
+	case BFI_LL_I2H_RXQ_STOP_RSP:
+		DO_CALLBACK(rxq_stop_cb);
+		break;
+	case BFI_LL_I2H_PORT_ADMIN_RSP:
+		DO_CALLBACK(port_admin_cb);
+		break;
+	case BFI_LL_I2H_STATS_GET_RSP:
+		bna_do_stats_update(dev, status);
+		DO_CALLBACK(stats_get_cb);
+		break;
+	case BFI_LL_I2H_STATS_CLEAR_RSP:
+		DO_CALLBACK(stats_clr_cb);
+		break;
+	case BFI_LL_I2H_LINK_DOWN_AEN:
+		DO_CALLBACK(link_down_cb);
+		break;
+	case BFI_LL_I2H_LINK_UP_AEN:
+		DO_CALLBACK(link_up_cb);
+		break;
+	case BFI_LL_I2H_DIAG_LOOPBACK_RSP:
+		DO_CALLBACK(set_diag_lb_cb);
+		break;
+	case BFI_LL_I2H_SET_PAUSE_RSP:
+		DO_CALLBACK(set_pause_cb);
+		break;
+	case BFI_LL_I2H_MTU_INFO_RSP:
+		DO_CALLBACK(mtu_info_cb);
+		break;
+	case BFI_LL_I2H_RX_RSP:
+		DO_CALLBACK(rxf_cb);
+		break;
+	case BFI_LL_I2H_CEE_DOWN_AEN:
+		break;
+	case BFI_LL_I2H_CEE_UP_AEN:
+		break;
+	default:
+		DPRINTK(WARNING, "cb(): unknown msg Id %d for LL class\n",
+			cmd_code);
+		break;
+	}
+}
+
+
+static enum bna_status_e
+bna_flush_mbox_q(struct bna_dev_s *dev, u8 wait_for_rsp)
+{
+	struct bna_mbox_q *q;
+	struct bna_mbox_cmd_qe *qe = NULL;
+	u8 msg_id = 0, msg_class = 0;
+
+	q = &dev->mbox_q;
+
+	if (bna_mbox_q_is_empty(q))
+		return BNA_OK;
+	if (q->posted != NULL && wait_for_rsp) {
+		qe = (struct bna_mbox_cmd_qe *)(q->posted);
+		/* The driver has to retry */
+		return BNA_BUSY;
+	}
+
+	while (!bna_mbox_q_is_empty(q)) {
+		qe = bna_mbox_q_first(q);
+		msg_class = ((struct bfi_mhdr_s *)(&qe->cmd.msg[0]))->msg_class;
+		msg_id = ((struct bfi_mhdr_s *)(&qe->cmd.msg[0]))->msg_id;
+
+
+		BNA_ASSERT(msg_class == BFI_MC_LL);
+
+		bna_do_drv_ll_cb(dev,  BFA_I2HM(msg_id),
+		    BFI_LL_CMD_NOT_EXEC, qe);
+		bna_mbox_deq(q);
+	}
+	/* Reinit the queue, i.e prod = cons = 0; */
+	bna_mbox_q_init(q);
+	return BNA_OK;
+}
+
+enum bna_status_e
+bna_cleanup(void *bna_dev)
+{
+	struct bna_dev_s *dev = (struct bna_dev_s *)bna_dev;
+
+	dev->msg_ctr = 0;
+
+	return bna_flush_mbox_q(dev, 0);
+}
+
+/**
+ * Check both command queues
+ * Write to mailbox if required
+ */
+static enum bna_status_e
+bna_chk_n_snd_q(struct bna_dev_s *dev)
+{
+	struct bna_mbox_cmd_qe *qe = NULL;
+	struct bna_mbox_q *q;
+	struct bfi_mhdr_s *mh = NULL;
+
+	q = &dev->mbox_q;
+
+	if ((bna_mbox_q_is_empty(q)) || (q->posted != NULL))
+		return BNA_OK;
+
+	qe = bna_mbox_q_first(q);
+	/* Do not post any more commands if disable pending */
+	if (dev->ioc_disable_pending == 1)
+		return BNA_OK;
+
+	mh = ((struct bfi_mhdr_s *)(&qe->cmd.msg[0]));
+	mh->mtag.i2htok = bna_os_htons(dev->msg_ctr);
+	dev->msg_ctr++;
+	bfa_ioc_mbox_queue(&dev->ioc, &qe->cmd);
+	q->posted = qe;
+
+	return BNA_OK;
+}
+
+enum bna_status_e
+bna_mbox_send(struct bna_dev_s *dev, void *cmd, u32 cmd_len,
+    void *cbarg)
+{
+	struct bna_mbox_cmd_qe *qe;
+	struct bna_mbox_q *q;
+
+	BNA_ASSERT(cmd_len <= BNA_MAX_MBOX_CMD_LEN);
+
+	if (dev->ioc_disable_pending) {
+		DPRINTK(WARNING,
+			"IOC Disable is pending :"
+			"Cannot queue Cmd class %d id %d\n",
+			mh->msg_class, mh->msg_id);
+		return BNA_FAIL;
+	}
+
+	if (!bfa_ioc_is_operational(&dev->ioc)) {
+		DPRINTK(ERR,
+			"IOC is not operational :"
+			"Cannot queue Cmd class %d id %d\n",
+			mh->msg_class, mh->msg_id);
+		return BNA_FAIL;
+	}
+
+	q = &dev->mbox_q;
+	qe = bna_mbox_enq(q, cmd, cmd_len, cbarg);
+	if (qe == NULL)
+		return BNA_FAIL;
+	return bna_chk_n_snd_q(dev);
+}
+
+
+/**
+ * Returns 1, if this is an aen, 0 otherwise
+ */
+static int
+bna_is_aen(u8 msg_id)
+{
+	return
+	   (msg_id == BFI_LL_I2H_LINK_DOWN_AEN ||
+	    msg_id == BFI_LL_I2H_LINK_UP_AEN ||
+	    msg_id == BFI_LL_I2H_CEE_DOWN_AEN ||
+	    msg_id == BFI_LL_I2H_CEE_UP_AEN);
+}
+
+static void
+bna_err_handler(struct bna_dev_s *dev, u32 intr_status)
+{
+	u32 curr_mask;
+
+	DPRINTK(DEBUG, "HW ERROR : INT statux 0x%x on port %d\n",
+		intr_status, dev->port);
+
+	bfa_ioc_error_isr(&dev->ioc);
+
+	/*
+	 * Disable all the bits in interrupt mask, including
+	 * the mbox & error bits.
+	 * This is required so that once h/w error hits, we don't
+	 * get into a loop.
+	 */
+	bna_intx_disable(dev, &curr_mask);
+
+	if (dev->mb_cbfns.hw_error_cb)
+		(dev->mb_cbfns.hw_error_cb)(dev->cbarg, 0);
+}
+
+void
+bna_ll_isr(void *llarg, struct bfi_mbmsg_s *msg)
+{
+	u32 aen = 0;
+	struct bna_dev_s *dev = (struct bna_dev_s *)llarg;
+	struct bna_mbox_cmd_qe *qe = NULL;
+	struct bna_mbox_q *mbox_q = NULL;
+	struct bfi_ll_rsp *mb_rsp = NULL;
+
+	mb_rsp = (struct bfi_ll_rsp *)(msg);
+
+	BNA_ASSERT(mb_rsp->mh.msg_class == BFI_MC_LL);
+
+	aen = bna_is_aen(mb_rsp->mh.msg_id);
+	if (!aen) {
+		mbox_q = &dev->mbox_q;
+
+		BNA_ASSERT(!bna_mbox_q_is_empty(mbox_q));
+		qe = bna_mbox_q_first(mbox_q);
+		BNA_ASSERT(mbox_q->posted == qe);
+
+		if (BFA_I2HM(((struct bfi_mhdr_s *)
+			(&qe->cmd.msg[0]))->msg_id) != mb_rsp->mh.msg_id) {
+			DPRINTK(ERR,
+			"Invalid Rsp Msg %d:%d (Expected %d:%d) on %d\n",
+			mb_rsp->mh.msg_class, mb_rsp->mh.msg_id,
+			((struct bfi_mhdr_s *)(&qe->cmd.msg[0]))->msg_class,
+			BFA_I2HM(((struct bfi_mhdr_s *)
+			(&qe->cmd.msg[0]))->msg_id),
+			dev->port);
+			BNA_ASSERT(0);
+			return;
+		}
+		bna_mbox_deq(mbox_q);
+		mbox_q->posted = NULL;
+	}
+	bna_do_drv_ll_cb(dev, mb_rsp->mh.msg_id, mb_rsp->error, qe);
+	bna_chk_n_snd_q(dev);
+}
+
+
+void
+bna_mbox_err_handler(struct bna_dev_s *dev, u32 intr_status)
+{
+	if (BNA_IS_ERR_INTR(intr_status)) {
+		bna_err_handler(dev, intr_status);
+		return;
+	}
+
+	if (BNA_IS_MBOX_INTR(intr_status))
+		bfa_ioc_mbox_isr(&dev->ioc);
+}
+
+/**
+ * bna_port_admin()
+ *
+ *   Enable (up) or disable (down) the interface administratively.
+ *
+ * @param[in]  dev	- pointer to BNA device structure
+ * @param[in]  enable - enable/disable the interface.
+ *
+ * @return BNA_OK or BNA_FAIL
+ */
+enum bna_status_e
+bna_port_admin(struct bna_dev_s *bna_dev, enum bna_enable_e enable)
+{
+	struct bna_dev_s *dev = (struct bna_dev_s *)bna_dev;
+	struct bfi_ll_port_admin_req ll_req;
+
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
+	ll_req.mh.mtag.i2htok = 0;
+
+	ll_req.up = enable;
+
+	/* send to f/w */
+	return bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+}
+/**
+ * bna_port_param_get()
+ *
+ *   Get the port parameters.
+ *
+ * @param[in]   dev	   - pointer to BNA device structure
+ * @param[out]  param_ptr - pointer to where the parameters will be returned.
+ *
+ * @return void
+ */
+void
+bna_port_param_get(struct bna_dev_s *dev, struct bna_port_param *param_ptr)
+{
+	param_ptr->supported = BNA_TRUE;
+	param_ptr->advertising = BNA_TRUE;
+	param_ptr->speed = BNA_LINK_SPEED_10Gbps;
+	param_ptr->duplex = BNA_TRUE;
+	param_ptr->autoneg = BNA_FALSE;
+	param_ptr->port = dev->port;
+}
+
+/**
+ * bna_port_mac_get()
+ *
+ *   Get the Burnt-in or permanent MAC address.  This function does not return
+ *   the MAC set thru bna_rxf_ucast_mac_set() but the one that is assigned to
+ *   the port upon reset.
+ *
+ * @param[in]  dev	 - pointer to BNA device structure
+ * @param[out] mac_ptr - Burnt-in or permanent MAC address.
+ *
+ * @return void
+ */
+void
+bna_port_mac_get(struct bna_dev_s *bna_dev, u8 *mac_ptr)
+{
+	struct bna_dev_s *dev = (struct bna_dev_s *)bna_dev;
+	mac_t mac;
+
+	mac = bfa_ioc_get_mac(&dev->ioc);
+
+	/* TODO : Use mac_t, remove memcpy */
+	bna_os_memcpy(mac_ptr, &mac, sizeof(mac_t));
+}
+
+/**
+ *	IOC Integration
+ */
+
+/**
+ *	bfa_iocll_cbfn
+ *	Structure for callbacks to be implemented by
+ *	the driver.
+ */
+static struct bfa_ioc_cbfn_s bfa_iocll_cbfn = {
+	bna_iocll_enable_cbfn,
+	bna_iocll_disable_cbfn,
+	bna_iocll_hbfail_cbfn,
+	bna_iocll_reset_cbfn
+};
+
+
+static void
+bna_iocll_memclaim(struct bna_dev_s *dev, struct bna_meminfo *mi)
+{
+
+	bfa_ioc_mem_claim(&dev->ioc, mi[BNA_DMA_MEM_T_ATTR].kva,
+	    mi[BNA_DMA_MEM_T_ATTR].dma);
+
+	if (bna_ioc_auto_recover)
+		bfa_ioc_debug_memclaim(&dev->ioc,
+		    mi[BNA_KVA_MEM_T_FWTRC].kva);
+}
+
+void
+bna_iocll_meminfo(struct bna_dev_s *dev, struct bna_meminfo *mi)
+{
+
+
+	mi[BNA_DMA_MEM_T_ATTR].len =
+	    BNA_ALIGN(bfa_ioc_meminfo(), BNA_PAGE_SIZE);
+
+	mi[BNA_KVA_MEM_T_FWTRC].len =
+	    bfa_ioc_debug_trcsz(bna_ioc_auto_recover);
+}
+
+void
+bna_iocll_attach(struct bna_dev_s *dev, void *bnad, struct bna_meminfo *meminfo,
+    struct bfa_pcidev_s *pcidev, struct bfa_trc_mod_s *trcmod,
+    struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
+{
+	bfa_ioc_attach(&dev->ioc, bnad, &bfa_iocll_cbfn, &dev->timer_mod,
+		       trcmod, aen, logm);
+	bfa_ioc_pci_init(&dev->ioc, pcidev, BFI_MC_LL);
+
+	bfa_ioc_mbox_regisr(&dev->ioc, BFI_MC_LL, bna_ll_isr, dev);
+	bna_iocll_memclaim(dev, meminfo);
+
+
+	bfa_timer_init(&dev->timer_mod);
+
+}
+
+/**
+ * FIXME :
+ * Either the driver or CAL should serialize
+ * this IOC disable
+ * Currently this is happening indirectly b'cos
+ * bfa_ioc_disable() is not called if there
+ * is an outstanding cmd in the queue, which
+ * could not be flushed.
+ */
+enum bna_status_e
+bna_iocll_disable(struct bna_dev_s *dev)
+{
+	enum bna_status_e ret;
+
+	dev->ioc_disable_pending = 1;
+	ret = bna_flush_mbox_q(dev, 1);
+	if (ret != BNA_OK) {
+		DPRINTK(WARNING, "Unable to flush Mbox Queues [%d]\n", ret);
+		return ret;
+	}
+
+	bfa_ioc_disable(&dev->ioc);
+	dev->ioc_disable_pending = 0;
+
+	return BNA_OK;
+}
+
+void
+bna_iocll_getinfo(struct bna_dev_s *dev, char *serial_num, u32 size)
+{
+	struct bfa_adapter_attr_s ad_attr;
+	u32 length;
+
+	bfa_ioc_get_adapter_attr(&dev->ioc, &ad_attr);
+	length = BNA_MIN(size, sizeof(ad_attr.serial_num));
+	bna_os_memcpy(serial_num, ad_attr.serial_num, length);
+}
+
+/* Dummy */
+/* FIXME : Delete once bfa_diag.c is fixed */
+void
+bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
+		bfa_boolean_t link_e2e_beacon)
+{
+}
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_iocll.h net-next-2.6-mod/drivers/net/bna/bna_iocll.h
--- net-next-2.6-orig/drivers/net/bna/bna_iocll.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_iocll.h	2009-10-31 21:34:47.872532000 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BNA_IOCLL_H__
+#define __BNA_IOCLL_H__
+
+#include <bfa_ioc.h>
+#include <bfa_timer.h>
+#include <bfi/bfi_ll.h>
+
+#define BNA_IOC_TIMER_PERIOD BFA_TIMER_FREQ /* 200 ms */
+
+/*
+ * LL specific IOC functions.
+ */
+void bna_iocll_meminfo(struct bna_dev_s *bna_dev, struct bna_meminfo *meminfo);
+void bna_iocll_attach(struct bna_dev_s *bna_dev, void *bnad,
+	struct bna_meminfo *meminfo, struct bfa_pcidev_s *pcidev,
+	struct bfa_trc_mod_s *trcmod, struct bfa_aen_s *aen,
+	struct bfa_log_mod_s *logmod);
+enum bna_status_e bna_iocll_disable(struct bna_dev_s *bna_dev);
+void bna_iocll_getinfo(struct bna_dev_s *bna_dev, char *serial_num, u32 size);
+#define bna_iocll_detach(dev) bfa_ioc_detach(&((dev)->ioc))
+#define bna_iocll_enable(dev) bfa_ioc_enable(&((dev)->ioc))
+#define bna_iocll_debug_fwsave(dev, trc_data, trc_len)		\
+	bfa_ioc_debug_fwsave(&((dev)->ioc), (trc_data), (trc_len))
+#define bna_iocll_debug_fwtrc(dev, trc_data, trc_len)		\
+	bfa_ioc_debug_fwtrc(&((dev)->ioc), (trc_data), (trc_len))
+#define bna_iocll_timer(dev) bfa_timer_beat(&((dev)->timer_mod))
+#define bna_iocll_getstats(dev, ioc_stats)	\
+	bfa_ioc_fetch_stats(&((dev)->ioc), (ioc_stats))
+#define bna_iocll_resetstats(dev) bfa_ioc_clr_stats(&((dev)->ioc))
+#define bna_iocll_getattr(dev, ioc_attr)	\
+	bfa_ioc_get_attr(&((dev)->ioc), (ioc_attr))
+
+/**
+ * Callback functions to be implemented by the driver
+ */
+void bna_iocll_enable_cbfn(void *bnad, enum bfa_status status);
+void bna_iocll_disable_cbfn(void *bnad);
+void bna_iocll_hbfail_cbfn(void *bnad);
+void bna_iocll_reset_cbfn(void *bnad);
+
+#endif /* __BNA_IOCLL_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_os.h net-next-2.6-mod/drivers/net/bna/bna_os.h
--- net-next-2.6-orig/drivers/net/bna/bna_os.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_os.h	2009-10-31 21:34:47.878536000 -0700
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See <license_file> for copyright and licensing details.
+ */
+
+/**
+ * Contains declarations of linux specific calls required for Brocade
+ * FCoE HBA driver implementation. Each OS has to provide this file.
+ */
+
+/**
+ *  bna_os.h Linux driver OS specific declarations.
+ */
+
+#ifndef __BNA_OS_H__
+#define __BNA_OS_H__
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h> /* Hack for ETH_ALEN: Do we care ? */
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/string.h>
+#else
+#include <sys/io.h>
+#endif
+
+#ifdef __KERNEL__
+
+#define BNA_PAGE_SIZE		PAGE_SIZE
+#define BNA_PAGE_SHIFT		PAGE_SHIFT
+
+#define BNA_ERR			KERN_ERR
+#define BNA_WARNING		KERN_WARNING
+#define BNA_NOTICE		KERN_NOTICE
+#define BNA_INFO		KERN_INFO
+#define BNA_DEBUG		KERN_DEBUG
+
+
+#ifdef DEBUG
+
+#define PFX "BNA: "
+#define DPRINTK(klevel, fmt, args...) do {  \
+		printk(KERN_##klevel PFX fmt, \
+		## args);      \
+} while (0)
+
+#ifdef BNA_ASSERT_PRINTK_ONLY
+#define BNA_ASSERT(p) do {						\
+	if (!(p))							\
+		printk(KERN_ERR "assert(%s) failed at %s:%d\n",		\
+		    #p, __FILE__, __LINE__);      \
+} while (0)
+#else
+#define BNA_ASSERT(p) do {						\
+	if (!(p)) {      \
+		printk(KERN_ERR "assert(%s) failed at %s:%d\n",		\
+		    #p, __FILE__, __LINE__);      \
+		BUG();      \
+	}								\
+} while (0)
+#endif
+
+#ifndef BNA_DEV_PRINTF
+#define BNA_DEV_PRINTF(bnad, level, fmt, arg...)			\
+		dev_printk(level, &(((bnad_t *)(bnad))			\
+			->pcidev->dev), fmt, ##arg);
+#endif
+
+#define BNA_PRINTF(level, fmt, arg...)					\
+		printk(level fmt, ##arg);
+
+#else /* DEBUG */
+
+#define BNA_ASSERT(p)
+#define BNA_DEV_PRINTF(bnad, level, fmt, arg...)
+#define BNA_PRINTF(level, fmt, arg...)
+
+#define DPRINTK(klevel, fmt, args...)   do { \
+		} while (0)
+
+#endif /* !DEBUG */
+
+#else /*  __KERNEL__ */
+
+#define BNA_ASSERT(p)
+
+#endif /*  !__KERNEL__ */
+
+#define bna_os_swap_3b(_x)				\
+	((((_x) & 0xff) << 16) |		\
+	((_x) & 0x00ff00) |			\
+	(((_x) & 0xff0000) >> 16))
+
+#define bna_os_swap_8b(_x) 				\
+     ((((_x) & 0xff00000000000000ull) >> 56)		\
+      | (((_x) & 0x00ff000000000000ull) >> 40)		\
+      | (((_x) & 0x0000ff0000000000ull) >> 24)		\
+      | (((_x) & 0x000000ff00000000ull) >> 8)		\
+      | (((_x) & 0x00000000ff000000ull) << 8)		\
+      | (((_x) & 0x0000000000ff0000ull) << 24)		\
+      | (((_x) & 0x000000000000ff00ull) << 40)		\
+      | (((_x) & 0x00000000000000ffull) << 56))
+
+#define bna_os_swap32(_x) 			\
+	((((_x) & 0xff) << 24) 		|	\
+	(((_x) & 0x0000ff00) << 8)	|	\
+	(((_x) & 0x00ff0000) >> 8)	|	\
+	(((_x) & 0xff000000) >> 24))
+
+
+#ifndef __BIGENDIAN
+#define bna_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
+				 (((_x) & 0x00ff) << 8)))
+
+#define bna_os_htonl(_x)	bna_os_swap32(_x)
+#define bna_os_htonll(_x)	bna_os_swap_8b(_x)
+
+#define bna_os_wtole(_x)   	(_x)
+#define bna_os_wtobe(_x)   	bna_os_swap32(_x)
+
+#define bna_os_dma_addr64(_x)	bna_os_swap_8b(_x)
+
+#else
+
+#define bna_os_htons(_x)   (_x)
+#define bna_os_htonl(_x)   (_x)
+#define bna_os_htonll(_x)  (_x)
+
+#define bna_os_wtole(_x)   bna_os_swap32(_x)
+#define bna_os_wtobe(_x)   (_x)
+
+#define bna_os_dma_addr64(_x)	(_x)
+
+#endif
+
+#define bna_os_ntohs(_x)   bna_os_htons(_x)
+#define bna_os_ntohl(_x)   bna_os_htonl(_x)
+#define bna_os_ntohll(_x)  bna_os_htonll(_x)
+#define bna_os_ntoh3b(_x)  bna_os_hton3b(_x)
+
+#define bna_os_memset	memset
+#define bna_os_memcpy	memcpy
+#define bna_os_udelay	udelay
+#define bna_os_vsprintf vsprintf
+
+#define bna_os_reg_read(_raddr)		readl(_raddr)
+#define bna_os_reg_write(_raddr, _val)	writel(_val, _raddr)
+#define bna_os_mem_read(_raddr, _off)      \
+			bna_os_ntohl(((u32 *)_raddr)[(_off) >> 2])
+#define bna_os_mem_write(_raddr, _off, _val)   \
+			(((u32 *)_raddr)[(_off) >> 2]) = bna_os_htonl(_val)
+
+#define bna_os_mem_readw(_raddr)      	\
+		bna_os_htonl(*((u32 *)(_raddr)))
+#define bna_os_mem_writew(_raddr, _val)   \
+		{*((u32 *)(_raddr)) = bna_os_htonl((_val))}
+
+/* Required for DMA address manipulation in IOC */
+#define bfa_os_u32(__pa64) ((__pa64) >> 32)
+
+#endif /* __BNA_OS_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_priv.h net-next-2.6-mod/drivers/net/bna/bna_priv.h
--- net-next-2.6-orig/drivers/net/bna/bna_priv.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_priv.h	2009-10-31 21:34:47.885533000 -0700
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See <license_file> for copyright and licensing details.
+ */
+
+/**
+ *  BNA register access macros.p
+ */
+
+#ifndef __BNA_PRIV_H__
+#define __BNA_PRIV_H__
+
+
+#define bna_mem_read(_raddr, _off)  bna_os_mem_read(_raddr, _off)
+#define bna_mem_write(_raddr, _off, _val)	\
+	bna_os_mem_write(_raddr, _off, _val)
+
+
+/**
+	Macros to declare a bit table
+ *
+ * @param[in] _table - bit table to be declared
+ * @param[in] _size  - size in bits
+ */
+#define BNA_BIT_TABLE_DECLARE(_table, _size)	\
+	(u32 _table[(_size) / 32])
+/**
+	Macros to set bits in  a bit table
+ *
+ * @param[in] _table - bit table to be declared
+ * @param[in] _bit	- bit to be set
+ */
+#define BNA_BIT_TABLE_SET(_table, _bit)				\
+	(_table[(_bit) / 32] |= (1 << ((_bit) & (32 - 1))))
+/**
+	Macros to clear bits in  a bit table
+ *
+ * @param[in] _table - bit table to be declared
+ * @param[in] _bit	- bit to be set
+ */
+#define BNA_BIT_TABLE_CLEAR(_table, _bit)	 	 \
+	(_table[(_bit) / 32] &= ~(1 << ((_bit) & (32 - 1))))
+/**
+	Macros to set bits in a 32 bit word
+ *
+ * @param[in] _word  - word in which bit is to be set
+ * @param[in] _bit	- bit to be set (starting at 0)
+ */
+#define BNA_BIT_WORD_SET(_word, _bit)		\
+	((_word) |= (1 << (_bit)))
+/**
+	Macros to clear bits in a 32 bit word
+ *
+ * @param[in] _word  - word in which bit is to be cleared
+ * @param[in] _bit	- bit to be cleared (starting at 0)
+ */
+#define BNA_BIT_WORD_CLEAR(_word, _bit) 	\
+	((_word) &= ~(1 << (_bit)))
+
+/**
+ * BNA_GET_PAGE_NUM()
+ *
+ *  Macro to calculate the page number for the
+ *  memory spanning multiple pages.
+ *
+ * @param[in] _base_page - Base Page Number for memory
+ * @param[in] _offset	- Offset for which page number
+ *	  	 is calculated
+ */
+#define BNA_GET_PAGE_NUM(_base_page, _offset)	\
+	((_base_page) + ((_offset) >> 15))
+/**
+ * BNA_GET_PAGE_OFFSET()
+ *
+ *  Macro to calculate the page offset for the
+ *  from the base offset (from the top of the block)
+ *  Each page 0x8000 (32KB) in size
+ *
+ * @param[in] _offset - Offset from the top of the block
+ */
+#define BNA_GET_PAGE_OFFSET(_offset)	\
+	((_offset) & 0x7fff)
+
+/**
+ * BNA_GET_WORD_OFFSET()
+ *
+ *  Macro to calculate the address of a word from
+ *  the base address. Needed to access H/W memory
+ *  as 4 byte words. Starts from 0.
+ *
+ * @param[in] _base_offset - Starting offset of the data
+ * @param[in] _word	 	- Word no. for which address is calculated
+ */
+#define BNA_GET_WORD_OFFSET(_base_offset, _word)	\
+	((_base_offset) + ((_word) << 2))
+/**
+ * BNA_GET_BYTE_OFFSET()
+ *
+ *  Macro to calculate the address of a byte from
+ *  the base address. Most of H/W memory is accessed
+ *  as 4 byte words, so use this macro carefully.
+ *  Starts from 0.
+ *
+ * @param[in] _base_offset - Starting offset of the data
+ * @param[in] _byte	 	- Byte no. for which address is calculated
+ */
+#define BNA_GET_BYTE_OFFSET(_base_offset, _byte)	\
+	((_base_offset) + (_byte))
+
+/**
+ * BNA_GET_MEM_BASE_ADDR()
+ *
+ *  Macro to calculate the base address of
+ *  any memory block given the bar0 address
+ *  and the memory base offset
+ *
+ * @param[in] _bar0	 - BARO address
+ * @param[in] _base_offset - Starting offset of the memory
+ */
+#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset)		\
+	((_bar0) + HW_BLK_HOST_MEM_ADDR		\
+	  + BNA_GET_PAGE_OFFSET((_base_offset)))
+
+/**
+ *  Structure which maps to Rx FnDb config
+ *  Size : 4 words
+ *  See catapult_spec.pdf, RxA for details
+ */
+struct bna_rx_fndb_ram {
+	u32 rss_prop;
+	u32 size_routing_props;
+	u32 rit_hds_mcastq;
+	u32 control_flags;
+};
+
+/**
+ *  Structure which maps to Tx FnDb config
+ *  Size : 1 word
+ *  See catapult_spec.pdf, TxA for details
+ */
+struct bna_tx_fndb_ram {
+	u32 vlan_n_ctrl_flags;
+};
+
+/**
+ *  Structure which maps to Unicast/Multicast CAM entry
+ *  Size : 2 words
+ *  See catapult_spec.pdf, LUT for details
+ */
+struct bna_cam {
+	u32 cam_mac_addr_47_32;	/*  31:16->res;15:0->MAC */
+	u32 cam_mac_addr_31_0;
+};
+
+/**
+ *  Structure which maps to Unicast RAM entry
+ *  Size : 1 word
+ *  See catapult_spec.pdf, LUT for details
+ */
+struct bna_ucast_mem {
+	u32 ucast_ram_entry;
+};
+
+/**
+ *  Structure which maps to VLAN RAM entry
+ *  Size : 1 word ?? Need to verify
+ *  See catapult_spec.pdf, LUT for details
+ */
+struct bna_vlan_mem {
+	u32 vlan_ram_entry;  /* FIXME */
+};
+#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\
+	(_bar0 + (HW_BLK_HOST_MEM_ADDR)  \
+	+ (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET))	\
+	+ (((_fn_id) & 0x3f) << 9)	  \
+	+ (((_vlan_id) & 0xfe0) >> 3))
+
+/**
+ *  Structure which maps to exact/approx MVT RAM entry
+ *  Size : 4 words
+ *  See catapult_spec.pdf, RxA for details
+ */
+struct bna_mvt_mem {
+	u32 reserved;
+	u32 fc_bit;	/*  31:1->res;0->fc_bit */
+	u32 ll_fn_63_32;	/*  LL fns 63 to 32 */
+	u32 ll_fn_31_0;	/*  LL fns 31 to 0 */
+};
+
+/**
+ *  Structure which maps to RxFn Indirection Table (RIT)
+ *  Size : 1 word
+ *  See catapult_spec.pdf, RxA for details
+ */
+struct bna_rit_mem {
+	u32 rxq_ids;	/*  31:12->res;11:0->two 6 bit RxQ Ids */
+};
+
+/**
+ *  Structure which maps to RSS Table entry
+ *  Size : 16 words
+ *  See catapult_spec.pdf, RAD for details
+ */
+struct bna_rss_mem {
+	u32 type_n_hash;	/*  31:12->res;
+			 11:8 ->protocol type
+			  7:0 ->hash index */
+	u32 hash_key[10];  /*  40 byte Toeplitz hash key */
+	u32 reserved[5];
+};
+
+/**
+ *  Structure which maps to RxQ Memory entry
+ *  Size : 16 words, entries are 32 words apart
+ *	  	 Alternate arrangement of RxQ & TxQ
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_rxq_mem {
+	u32 pg_tbl_addr_lo;
+	u32 pg_tbl_addr_hi;
+	u32 cur_q_entry_lo;
+	u32 cur_q_entry_hi;
+#if 0
+	u32 nxt_pg_addr_lo;
+	u32 nxt_pg_addr_hi;
+#endif
+	u32 reserved1;
+	u32 reserved2;
+	u32 pg_cnt_n_prd_ptr;/*  31:16->total page count
+			15:0 ->producer pointer (index?)*/
+	u32 entry_n_pg_size; /*  31:16->entry size
+			15:0 ->page size */
+	u32 sg_n_cq_n_cns_ptr; /* 31:28->reserved; 27:24->sg count
+			23:16->CQ; 15:0->consumer pointer(index?) */
+	u32 buf_sz_n_q_state; /*  31:16->buffer size; 15:0-> Q state */
+	u32 next_qid;		/*  17:10->next QId */
+	u32 reserved3;
+	u32 reserved4[4];
+};
+
+
+/**
+ *  Structure which maps to TxQ Memory entry
+ *  Size : 16 words, entries are 32 words apart
+ *	  	 Alternate arrangement of RxQ & TxQ
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_txq_mem {
+	u32 pg_tbl_addr_lo;
+	u32 pg_tbl_addr_hi;
+	u32 cur_q_entry_lo;
+	u32 cur_q_entry_hi;
+#if 0	/* obsolete, now replaced by reserved fields */
+	u32 nxt_pg_addr_lo
+	u32 nxt_pg_addr_hi;
+#endif
+	u32 reserved1;
+	u32 reserved2;
+	u32 pg_cnt_n_prd_ptr;/*  31:16->total page count
+			15:0 ->producer pointer (index?)*/
+	u32 entry_n_pg_size; /*  31:16->entry size
+			15:0 ->page size */
+	u32 int_blk_n_cns_ptr;/*  31:24->Int Blk Id; 23:16->Int Blk Offset
+			15:0 ->consumer pointer(index?) */
+	u32 cns_ptr2_n_q_state;/* 31:16->cons. ptr 2; 15:0-> Q state */
+	u32 nxt_qid_n_fid_n_pri;/*  17:10->next QId;9:3->FID;2:0->Priority */
+	u32 wvc_n_cquota_n_rquota; /*  31:24->WI Vector Count;
+			 23:12->Cfg Quota;
+			 11:0 ->Run Quota */
+	u32 reserved3[4];
+};
+
+/**
+ *  Structure which maps to RxQ and TxQ Memory entry
+ *  Size : 32 words, entries are 32 words apart
+ *	  	 Alternate arrangement of RxQ & TxQ
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_rxtx_q_mem {
+	struct bna_rxq_mem rxq;
+	struct bna_txq_mem txq;
+};
+
+/**
+ *  Structure which maps to CQ Memory entry
+ *  Size : 16 words
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_cq_mem {
+	u32 pg_tbl_addr_lo;
+	u32 pg_tbl_addr_hi;
+	u32 cur_q_entry_lo;
+	u32 cur_q_entry_hi;
+#if 0
+	u32 nxt_pg_addr_lo;
+	u32 nxt_pg_addr_hi;
+#endif
+	u32 reserved1;
+	u32 reserved2;
+	u32 pg_cnt_n_prd_ptr;/*  31:16->total page count
+			15:0 ->producer pointer (index?)*/
+	u32 entry_n_pg_size; /*  31:16->entry size
+			15:0 ->page size */
+	u32 int_blk_n_cns_ptr;/*  31:24->Int Blk Id; 23:16->Int Blk Offset
+			15:0 ->consumer pointer(index?) */
+	u32 q_state;		 /*  31:16->reserved; 15:0-> Q state */
+	u32 reserved3[2];
+	u32 reserved4[4];
+};
+
+/**
+ *  Structure which maps to Interrupt Block Memory entry
+ *  Size : 8 words (used: 5 words)
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_ib_blk_mem {
+	u32 host_addr_lo;
+	u32 host_addr_hi;
+	u32 clsc_n_ctrl_n_msix;/*  31:24->coalescing;
+			  23:16->coalescing cfg;
+			  15:8 ->control;
+				7:0 ->msix; */
+	u32 ipkt_n_ent_n_idxof;
+	u32 ipkt_cnt_cfg_n_unacked;
+
+	u32 reserved[3];
+};
+
+/**
+ *  Structure which maps to Index Table Block Memory entry
+ *  Size : 1 word
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_idx_tbl_mem {
+	u32 idx;	  /*  31:16->res;15:0->idx; */
+};
+
+/**
+ *  Structure which maps to Doorbell QSet Memory,
+ *  Organization of Doorbell address space for a
+ *  QSet (RxQ, TxQ, Rx IB, Tx IB)
+ *  For Non-VM qset entries are back to back.
+ *  Size : 128 bytes / 4K bytes for Non-VM / VM
+ *  See catapult_spec.pdf, HQM for details
+ */
+struct bna_doorbell_qset {
+	u32 rxq[0x20 >> 2];
+	u32 txq[0x20 >> 2];
+	u32 ib0[0x20 >> 2];
+	u32 ib1[0x20 >> 2];
+};
+
+
+#define BNA_GET_DOORBELL_BASE_ADDR(_bar0)	\
+	((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR)
+
+
+/**
+ * BNA_GET_DOORBELL_ENTRY_OFFSET()
+ *
+ *  Macro to calculate the offset of the Doorbell QSet
+ *  in the Non VM case.
+ *  Entries are 128 bytes apart. Does not need a page
+ *  number register for access.
+ *
+ * @param[in] _entry - Entry Number
+ */
+#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry)		\
+	((HQM_DOORBELL_BLK_BASE_ADDR)		\
+	+ (_entry << 7))
+/**
+ * BNA_GET_DOORBELL_VM_ENTRY_OFFSET()
+ *
+ *  Macro to calculate the offset of the Doorbell QSet
+ *  in the VM case.
+ *  Entries are 4K (0x1000) bytes apart.
+ *  Does not need a page number register for access.
+ *
+ * @param[in] _entry - Entry Number
+ */
+#define BNA_GET_DOORBELL_VM_ENTRY_OFFSET(_entry)	\
+	((HQM_DOORBELL_VM_BLK_BASE_ADDR)	\
+	+ (_entry << 12))
+
+/**
+ * BNA_GET_PSS_SMEM_PAGE_NUM()
+ *
+ *  Macro to calculate the page number of PSS SMEM
+ *  block from a linear offset
+ *
+ * @param[in] _loff - Linear offset from the top of memory
+ */
+#define BNA_GET_PSS_SMEM_PAGE_NUM(_loff)		\
+	(BNA_GET_PAGE_NUM(PSS_SMEM_BLK_PG_NUM, (_loff)))
+/**
+ * BNA_GET_PSS_SMEM_PAGE_OFFSET()
+ *
+ *  Macro to calculate the page offset from the top
+ *  of a PSS SMEM page, for a given linear offset
+ *
+ * @param[in] _loff - Linear offset from the top of memory
+ */
+#define BNA_GET_PSS_SMEM_PAGE_OFFSET(_loff)	 	 \
+	(PSS_SMEM_BLK_MEM_ADDR  		\
+	+ BNA_GET_PAGE_OFFSET((_loff)))
+
+/**
+ * BNA_GET_MBOX_PAGE_NUM()
+ *
+ *  Macro to calculate the page number of HostFn<->LPU/
+ *  LPU<->HostFn Mailbox block from a linear offset
+ *
+ * @param[in] _loff - Linear offset from the top of memory
+ */
+#define BNA_GET_MBOX_PAGE_NUM(_loff)			\
+	(BNA_GET_PAGE_NUM(CPQ_BLK_PG_NUM, (_loff)))
+/**
+ * BNA_GET_HOSTFN_LPU_MBOX_PAGE_OFFSET()
+ *
+ *  Macro to calculate the HostFn<->LPU
+ *  Mailbox page offset from the linear offset
+ *
+ * @param[in] _loff - Linear offset in bytes from the top of memory
+ */
+#define BNA_GET_HOSTFN_LPU_MBOX_PAGE_OFFSET(_loff)		\
+	(HOSTFN_LPU_MBOX + BNA_GET_PAGE_OFFSET((_loff)))
+/**
+ * BNA_GET_LPU_HOSTFN_MBOX_PAGE_OFFSET()
+ *
+ *  Macro to calculate the LPU<->HostFn
+ *  Mailbox page offset from the linear offset
+ *
+ * @param[in] _loff - Linear offset from the top of memory
+ */
+#define BNA_GET_LPU_HOSTFN_MBOX_PAGE_OFFSET(_loff)		\
+	(LPU_HOSTFN_MBOX + BNA_GET_PAGE_OFFSET((_loff)))
+
+
+#define bna_hw_stats_to_stats bna_os_dma_addr64
+
+void bna_mbox_q_init(struct bna_mbox_q *q);
+
+#define BNA_80K_PKT_RATE		 80000
+#define BNA_70K_PKT_RATE		 70000
+#define BNA_60K_PKT_RATE		 60000
+#define BNA_50K_PKT_RATE		 50000
+#define BNA_40K_PKT_RATE		 40000
+#define BNA_30K_PKT_RATE		 30000
+#define BNA_20K_PKT_RATE		 20000
+#define BNA_10K_PKT_RATE		 10000
+
+/**
+ * Defines are in order of decreasing load
+ * i.e BNA_HIGH_LOAD_3 has the highest load
+ * and BNA_LOW_LOAD_3 has the lowest load.
+ */
+
+#define BNA_HIGH_LOAD_4		0 	/* r >= 80 */
+#define BNA_HIGH_LOAD_3		1	/* 60 <= r < 80 */
+#define BNA_HIGH_LOAD_2		2	/* 50 <= r < 60 */
+#define BNA_HIGH_LOAD_1		3	/* 40 <= r < 50 */
+#define BNA_LOW_LOAD_1		4	/* 30 <= r < 40 */
+#define BNA_LOW_LOAD_2		5	/* 20 <= r < 30 */
+#define BNA_LOW_LOAD_3		6	/* 10 <= r < 20 */
+#define BNA_LOW_LOAD_4		7	/* r  <  10 K */
+#define BNA_LOAD_TYPES		BNA_LOW_LOAD_4
+
+#define BNA_BIAS_TYPES		2 	/* small : small > large*2 */
+					/* large : if small is false */
+
+#endif /* __BNA_PRIV_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bnad_compat.h net-next-2.6-mod/drivers/net/bna/bnad_compat.h
--- net-next-2.6-orig/drivers/net/bna/bnad_compat.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bnad_compat.h	2009-10-31 21:34:47.892532000 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _BNAD_COMPAT_H_
+#define _BNAD_COMPAT_H_
+
+#include <linux/version.h>
+
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(netdev) do { } while (0)
+#endif
+
+#ifndef SET_NETDEV_DEV
+#define SET_NETDEV_DEV(netdev, dev) do { } while (0)
+#endif
+
+#ifndef module_param
+#define module_param(name, type, perm)	MODULE_PARM(name, "i");
+#endif
+
+#ifndef NET_IP_ALIGN
+#define NET_IP_ALIGN 2
+#endif
+
+#ifndef NETDEV_TX_OK
+#define NETDEV_TX_OK 0 /* driver took care of the packet */
+#endif
+
+#ifndef NETDEV_TX_BUSY
+#define NETDEV_TX_BUSY 1 /* driver tx path was busy */
+#endif
+
+#ifndef NETDEV_TX_LOCKED
+#define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */
+#endif
+
+#ifndef ALIGN
+#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
+#endif
+
+#ifndef ETH_FCS_LEN
+#define ETH_FCS_LEN 4
+#endif
+
+#ifndef CHECKSUM_PARTIAL
+#define CHECKSUM_PARTIAL CHECKSUM_HW
+#endif
+
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+#ifndef SKB_DATAREF_SHIFT
+#define skb_header_cloned(_skb) 0
+#endif
+
+#ifndef VERIFY_WRITE
+#define VERIFY_WRITE 1
+#endif
+
+#ifndef VERIFY_READ
+#define VERIFY_READ 0
+#endif
+
+#ifndef dev_err
+#define dev_err(dev, format, arg...)	\
+	printk(KERN_ERR "bna: " format , ## arg)
+#endif
+#ifndef dev_info
+#define dev_info(dev, format, arg...)	\
+	printk(KERN_INFO "bna: " format , ## arg)
+#endif
+#ifndef dev_warn
+#define dev_warn(dev, format, arg...)	\
+	printk(KERN_WARNING "bna: " format , ## arg)
+#endif
+
+#endif /* _BNAD_COMPAT_H_ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bnad_defs.h net-next-2.6-mod/drivers/net/bna/bnad_defs.h
--- net-next-2.6-orig/drivers/net/bna/bnad_defs.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bnad_defs.h	2009-10-31 21:34:47.899534000 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _BNAD_DEFS_H_
+#define _BNAD_DEFS_H_
+
+#define BNAD_NAME	"bna"
+#define BNAD_VERSION	"2.0.0.0"
+
+#ifndef PCI_VENDOR_ID_BROCADE
+#define PCI_VENDOR_ID_BROCADE	0x1657
+#endif
+
+#ifndef PCI_DEVICE_ID_BROCADE_CATAPULT
+#define PCI_DEVICE_ID_BROCADE_CATAPULT	0x0014
+#endif
+
+#endif /* _BNAD_DEFS_H_ */
diff -ruP net-next-2.6-orig/drivers/net/bna/cna.h net-next-2.6-mod/drivers/net/bna/cna.h
--- net-next-2.6-orig/drivers/net/bna/cna.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/cna.h	2009-10-31 21:34:47.906532000 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __CNA_H__
+#define __CNA_H__
+
+#include <cs/bfa_trc.h>
+#include <defs/bfa_defs_types.h>
+
+extern char bfa_version[];
+void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
+
+#endif /* __CNA_H__ */

^ permalink raw reply

* Subject: [PATCH 2/6] bna: Brocade 10Gb Ethernet device driver
From: Rasesh Mody @ 2009-11-01  5:03 UTC (permalink / raw)
  To: netdev; +Cc: adapter_linux_open_src_team

From: Rasesh Mody <rmody@brocade.com>

This is patch 2/6 which contains linux driver source for
Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
Re-based source against net-next-2.6 and re-submitting the
patch with few fixes.

We wish this patch to be considered for inclusion in net-next-2.6

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 bfa_timer.c    |   97 ++
 bfad_fwimg.c   |  102 ++
 bna_fn.c       | 1982 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bna_queue.c    |  496 ++++++++++++++
 bnad_ethtool.c | 1094 +++++++++++++++++++++++++++++++
 5 files changed, 3771 insertions(+)

diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_timer.c net-next-2.6-mod/drivers/net/bna/bfa_timer.c
--- net-next-2.6-orig/drivers/net/bna/bfa_timer.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_timer.c	2009-10-31 21:34:47.660532000 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#include <bfa_timer.h>
+#include <cs/bfa_debug.h>
+
+void
+bfa_timer_init(struct bfa_timer_mod_s *mod)
+{
+	INIT_LIST_HEAD(&mod->timer_q);
+}
+
+void
+bfa_timer_beat(struct bfa_timer_mod_s *mod)
+{
+	struct list_head        *qh = &mod->timer_q;
+	struct list_head        *qe, *qe_next;
+	struct bfa_timer_s *elem;
+	struct list_head         timedout_q;
+
+	INIT_LIST_HEAD(&timedout_q);
+
+	qe = bfa_q_next(qh);
+
+	while (qe != qh) {
+		qe_next = bfa_q_next(qe);
+
+		elem = (struct bfa_timer_s *) qe;
+		if (elem->timeout <= BFA_TIMER_FREQ) {
+			elem->timeout = 0;
+			list_del(&elem->qe);
+			list_add_tail(&elem->qe, &timedout_q);
+		} else {
+			elem->timeout -= BFA_TIMER_FREQ;
+		}
+
+		qe = qe_next;	/* go to next elem */
+	}
+
+	/*
+	 * Pop all the timeout entries
+	 */
+	while (!list_empty(&timedout_q)) {
+		bfa_q_deq(&timedout_q, &elem);
+		elem->timercb(elem->arg);
+	}
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+		    void (*timercb) (void *), void *arg, unsigned int timeout)
+{
+
+	bfa_assert(timercb != NULL);
+	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+
+	timer->timeout = timeout;
+	timer->timercb = timercb;
+	timer->arg = arg;
+
+	list_add_tail(&timer->qe, &mod->timer_q);
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_stop(struct bfa_timer_s *timer)
+{
+	bfa_assert(!list_empty(&timer->qe));
+
+	list_del(&timer->qe);
+}
diff -ruP net-next-2.6-orig/drivers/net/bna/bfad_fwimg.c net-next-2.6-mod/drivers/net/bna/bfad_fwimg.c
--- net-next-2.6-orig/drivers/net/bna/bfad_fwimg.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfad_fwimg.c	2009-10-31 21:34:47.667534000 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ *  bfad_fwimg.c Linux driver PCI interface module.
+ */
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_version.h>
+#include <defs/bfa_defs_pci.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <bfa_fwimg_priv.h>
+
+u32 bfi_image_ct_size;
+u32 bfi_image_cb_size;
+u32 *bfi_image_ct;
+u32 *bfi_image_cb;
+
+
+#define	BFAD_FW_FILE_CT	"ctfw.bin"
+#define	BFAD_FW_FILE_CB	"cbfw.bin"
+
+u32 *
+bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+			u32 *bfi_image_size, char *fw_name)
+{
+	const struct firmware *fw;
+
+	if (request_firmware(&fw, fw_name, &pdev->dev)) {
+		printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
+		goto error;
+	}
+
+	*bfi_image = vmalloc(fw->size);
+	if (NULL == *bfi_image) {
+		printk(KERN_ALERT "Fail to allocate buffer for fw image "
+			"size=%x!\n", (u32) fw->size);
+		goto error;
+	}
+
+	memcpy(*bfi_image, fw->data, fw->size);
+	*bfi_image_size = fw->size/sizeof(u32);
+
+	return *bfi_image;
+
+error:
+	return NULL;
+}
+
+u32 *
+bfad_get_firmware_buf(struct pci_dev *pdev)
+{
+	if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
+		if (bfi_image_ct_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct,
+				&bfi_image_ct_size, BFAD_FW_FILE_CT);
+		return bfi_image_ct;
+	} else {
+		if (bfi_image_cb_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_cb,
+				&bfi_image_cb_size, BFAD_FW_FILE_CB);
+		return bfi_image_cb;
+	}
+}
+
+u32 *
+bfi_image_ct_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_ct + off); }
+
+u32 *
+bfi_image_cb_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_cb + off); }
+
+
+char bfa_version[BFA_VERSION_LEN] = "rmody_pvt_bld 08/26/2009 11.26.03";
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_fn.c net-next-2.6-mod/drivers/net/bna/bna_fn.c
--- net-next-2.6-orig/drivers/net/bna/bna_fn.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_fn.c	2009-10-31 21:34:47.675535000 -0700
@@ -0,0 +1,1982 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ *    Copyright (c) 2007-2008 Brocade Communications Systems, Inc.
+ *    All rights reserved.
+ *
+ *    @file bna_fn.c BNA Rx and Tx Function Management
+ */
+
+#include <bna_os.h>
+#include "bna.h"
+#include "bna_hwreg.h"
+#include "bna_priv.h"
+#include <bfi/bfi_ll.h>
+#include <bfi/bfi_cee.h>
+
+
+/*
+ * 12 bit Max VLAN Id mask used to
+ * wrap overflowing VLANs wraps around the
+ * max value of 4095
+ */
+#define BNA_MAX_VLAN_ID_MASK	0x00000fff
+
+const struct bna_chip_regs_offset reg_offset[] =
+	{ {HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS,
+		HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0},
+	  {HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS,
+		HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1},
+	  {HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS,
+		HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2},
+	  {HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS,
+		HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3},
+	};
+/**
+ * bna_init()
+ *
+ *   Called by the driver during initialization. The driver is
+ *   expected to allocate bna_dev_s structure for the BNA layer.
+ *
+ * @param[in]  bar0        - BAR0 value
+ * @param[in]  bna_handle  - pointer to BNA device structure
+ *      		     allocated by the calling driver
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_init(struct bna_dev_s *dev, void *bar0, void *stats,
+	 struct bna_dma_addr stats_dma, struct bfa_trc_mod_s *trcmod)
+{
+	u32 pcifn;
+
+	memset(dev, 0, sizeof(struct bna_dev_s));
+
+	dev->trcmod = trcmod;
+
+	dev->bar0 = (u8 *)bar0;
+	dev->hw_stats = (struct bfi_ll_stats *)stats;
+	dev->hw_stats_dma.msb = stats_dma.msb;
+	dev->hw_stats_dma.lsb = stats_dma.lsb;
+
+	dev->rxf_promiscuous_id = BNA_RXF_ID_NONE;
+	dev->rxf_default_id = BNA_RXF_ID_NONE;
+
+	pcifn = bna_reg_read(dev->bar0 + FNC_ID_REG);
+	pcifn = bna_reg_read(dev->bar0 + FNC_ID_REG);
+	BNA_ASSERT(pcifn <= 3);
+
+	dev->regs.page_addr = dev->bar0 + reg_offset[pcifn].page_addr;
+	dev->regs.fn_int_status = dev->bar0 + reg_offset[pcifn].fn_int_status;
+	dev->regs.fn_int_mask = dev->bar0 + reg_offset[pcifn].fn_int_mask;
+
+	if (pcifn < 3)
+		dev->port = 0;
+	else
+		dev->port = 1;
+
+	dev->pci_fn = pcifn;
+	DPRINTK(DEBUG, "LL Driver Using PCI fn (%d)\n", dev->pci_fn);
+
+	dev->ioc_disable_pending = 0;
+}
+
+/**
+ * bna_uninit()
+ *
+ *   Called by the driver during removal/unload.
+ *
+ * @param[in]  bna_handle  - pointer to BNA device structure
+ *      		     allocated by the calling driver
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_uninit(void *bna_handle)
+{
+	return BNA_OK;
+}
+
+/**
+ *  bna_rit_config_set()
+ *
+ *  Loads RIT entries "rit" into RIT starting from RIT index "rit_id".
+ *  Care must be taken not to overlap regions within the RIT.
+ *
+ * @param[in]  dev          - pointer to BNA device structure
+ * @param[in]  rit_offset   - offset into the RIT
+ * @param[in]  rit          - RIT entry
+ * @param[in]  rit_size     - size of RIT entry
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_rit_config_set(struct bna_dev_s *dev, unsigned int rit_offset,
+		    const struct bna_rit_entry rit[], unsigned int rit_size)
+{
+	int i;
+
+	struct bna_rit_mem *rit_mem;
+
+	BNA_ASSERT(BNA_POWER_OF_2(rit_size));
+	BNA_ASSERT((rit_offset + rit_size) < BNA_RIT_SIZE);
+
+	rit_mem = (struct bna_rit_mem *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, FUNCTION_TO_RXQ_TRANSLATE);
+
+	dev->rit_size[rit_offset] = rit_size;
+
+	bna_reg_write(dev->regs.page_addr,
+		BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + dev->port,
+		FUNCTION_TO_RXQ_TRANSLATE));
+
+	for (i = 0;  i < rit_size;  i++) {
+		bna_mem_writew(&rit_mem[i + rit_offset],
+		    rit[i].large_rxq_id << 6 | rit[i].small_rxq_id);
+	}
+}
+
+/**
+ * bna_rxf_config_set()
+ *
+ *   For RxF "rxf_id", it configures RxF based on "cfg_ptr", and indicates
+ *   to the statistics collector to collect statistics for this Rx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  cfg_ptr - pointer to rx-function configuration.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_config_set(struct bna_dev_s *dev, unsigned int rxf_id,
+				 const struct bna_rxf_config *cfg_ptr)
+{
+	u32 i;
+
+	struct bna_rss_mem *rss_mem;
+	struct bna_rx_fndb_ram *rx_fndb_ram;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	rss_mem = (struct bna_rss_mem *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, RSS_TABLE_BASE_OFFSET);
+	rx_fndb_ram = (struct bna_rx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, RX_FNDB_RAM_BASE_OFFSET);
+
+	/* Need to revisit, don't do this check */
+	if (((cfg_ptr->flags & BNA_RXF_CF_SM_LG_RXQ)) &&
+	    (cfg_ptr->hds.type == 1)) {
+		/* HDS and small-large RxQs are mutually exclusive */
+		DPRINTK(ERR,
+			"Small/Large & HDS cannot be set simultaneously\n");
+		return BNA_FAIL;
+	}
+
+	if (cfg_ptr->flags & BNA_RXF_CF_RSS_ENABLE) {
+		BNA_ASSERT(cfg_ptr->rss.hash_mask ==
+		    dev->rit_size[cfg_ptr->rit_offset] - 1);
+
+		/* configure RSS Table */
+		bna_reg_write(dev->regs.page_addr, BNA_GET_PAGE_NUM(
+			RAD0_MEM_BLK_BASE_PG_NUM + dev->port,
+			RSS_TABLE_BASE_OFFSET));
+
+		/* temporarily disable RSS, while hash value is being written */
+		bna_mem_writew(&rss_mem[0].type_n_hash, 0);
+
+		for (i = 0; i < BNA_RSS_HASH_KEY_LEN; i++) {
+			bna_mem_writew(
+				&rss_mem[0].hash_key[(
+				BNA_RSS_HASH_KEY_LEN - 1) - i],
+			    bna_os_htonl(cfg_ptr->rss.toeplitz_hash_key[i]));
+		}
+
+		bna_mem_writew(&rss_mem[0].type_n_hash, cfg_ptr->rss.type |
+				cfg_ptr->rss.hash_mask);
+
+	}
+	/* configure RxF based on "cfg_ptr" */
+	bna_reg_write(dev->regs.page_addr, BNA_GET_PAGE_NUM(
+		LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+			RX_FNDB_RAM_BASE_OFFSET));
+
+	/* we always use RSS table 0 */
+	bna_mem_writew(&rx_fndb_ram[rxf_id].rss_prop,
+		       cfg_ptr->flags & BNA_RXF_CF_RSS_ENABLE);
+
+	/* small large buffer enable/disable */
+	bna_mem_writew(&rx_fndb_ram[rxf_id].size_routing_props,
+		      (cfg_ptr->flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80);
+
+	/* RIT offset, HDS forced offset, multicast RxQ Id*/
+	bna_mem_writew(&rx_fndb_ram[rxf_id].rit_hds_mcastq,
+			(cfg_ptr->rit_offset << 16) |
+			(cfg_ptr->hds.forced_offset << 8) |
+			(cfg_ptr->hds.type & BNA_HDS_FORCED) |
+			cfg_ptr->mcast_rxq_id);
+
+	/* default vlan tag, default function enable, strip vlan bytes,
+	   HDS type, header size */
+	bna_mem_writew(&rx_fndb_ram[rxf_id].control_flags,
+		      (cfg_ptr->default_vlan << 16) | (cfg_ptr->flags &
+			(BNA_RXF_CF_DEFAULT_VLAN |
+			BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE |
+			 BNA_RXF_CF_VLAN_STRIP)) |
+			(cfg_ptr->hds.type & ~BNA_HDS_FORCED) |
+			cfg_ptr->hds.header_size);
+
+	/* turn on statistics collection for this RxF */
+	dev->rxf_active |= ((u64)1 << rxf_id);
+	return BNA_OK;
+}
+
+/**
+ * bna_rxf_config_clear()
+ *
+ *   For RxF "rxf_id", it clear its configuration and indicates to the
+ *   statistics collector to stop collecting statistics for this
+ *   Rx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_rxf_config_clear(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	struct bna_rx_fndb_ram *rx_fndb_ram;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	rx_fndb_ram = (struct bna_rx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, RX_FNDB_RAM_BASE_OFFSET);
+
+	/* clear configuration of RxF base */
+	bna_reg_write(dev->regs.page_addr,
+	    BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+	    (dev->port * 2), RX_FNDB_RAM_BASE_OFFSET));
+
+	/* we always use RSS table 0 */
+	bna_mem_writew(&rx_fndb_ram[rxf_id].rss_prop, 0);
+
+	/* small large buffer enable/disable */
+	bna_mem_writew(&rx_fndb_ram[rxf_id].size_routing_props, 0x80);
+
+	/* RIT offset, HDS forced offset, multicast RxQ Id*/
+	bna_mem_writew(&rx_fndb_ram[rxf_id].rit_hds_mcastq, 0);
+
+	/* default vlan tag, default function enable, strip vlan bytes,
+	   HDS type, header size */
+	bna_mem_writew(&rx_fndb_ram[rxf_id].control_flags, 0);
+
+	/* turn off statistics collection for this RxF */
+	dev->rxf_active &= ~((u64)1 << rxf_id);
+}
+
+/**
+ * bna_rxf_disable()
+ *
+ *  Disables the Rx Function without clearing the configuration
+ *  Also disables collection of statistics.
+ *
+ * @param[in] dev   	- Pointer to BNA device handle
+ * @param[in] rxf_id    - Id of the Rx Function to be disabled
+ *
+ * @return    BNA_OK if mbox command succeeded, else BNA_FAIL
+ */
+enum bna_status_e
+bna_rxf_disable(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	struct bfi_ll_rxf_multi_req ll_req;
+	u64 bit_mask = 1 << rxf_id;
+	enum bna_status_e status;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+	ll_req.rxf_id_mask[0] = bna_os_htonl((u32)bit_mask);
+	ll_req.rxf_id_mask[1] = bna_os_htonl((u32)(bit_mask >> 32));
+	ll_req.enable = 0;
+
+	status = bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+	if (!status)
+		dev->rxf_active &= ~bit_mask;
+	return status;
+}
+
+
+/* TODO : Delete when Windows migration is complete */
+void
+bna_rxf_disable_old(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	struct bna_rx_fndb_ram *rx_fndb_ram;
+	u32 ctl_flags;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	/* Clear the vlan table first, before writing to the Rx Fn DB */
+	bna_rxf_vlan_del_all(dev, rxf_id);
+
+	rx_fndb_ram = (struct bna_rx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, RX_FNDB_RAM_BASE_OFFSET);
+
+	bna_reg_write(dev->regs.page_addr,
+		BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+		RX_FNDB_RAM_BASE_OFFSET));
+
+	ctl_flags = bna_mem_readw(&rx_fndb_ram[rxf_id].control_flags);
+
+	/* Enable setting of the default vlan tag for untagged packets */
+	/* Don't need to store these already there in the BNA config */
+	ctl_flags |= BNA_RXF_CF_DEFAULT_VLAN;
+
+	bna_mem_writew(&rx_fndb_ram[rxf_id].control_flags, ctl_flags);
+
+	/* turn off statistics collection for this RxF */
+	dev->rxf_active &= ~((u64)1 << rxf_id);
+}
+
+/**
+ * bna_rxf_enable()
+ *
+ *  Enables the Rx Function
+ *
+ * @param[in] dev   	- Pointer to BNA device handle
+ * @param[in] rxf_id    - Id of the Rx Function to be disabled
+ *
+ * @return    BNA_OK if mbox command succeeded, else BNA_FAIL
+ */
+enum bna_status_e
+bna_rxf_enable(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	struct bfi_ll_rxf_multi_req ll_req;
+	u64 bit_mask = 1 << rxf_id;
+	enum bna_status_e status;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+	ll_req.rxf_id_mask[0] = bna_os_htonl((u32)bit_mask);
+	ll_req.rxf_id_mask[1] = bna_os_htonl((u32)(bit_mask >> 32));
+	ll_req.enable = 1;
+
+	status = bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+	if (!status)
+		dev->rxf_active |= bit_mask;
+	return status;
+}
+
+
+enum bna_status_e
+bna_multi_rxf_active(struct bna_dev_s *dev, u64 rxf_id_mask, u8 enable)
+{
+	struct bfi_ll_rxf_multi_req ll_req;
+	enum bna_status_e status;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+	ll_req.rxf_id_mask[0] = bna_os_htonl((u32)rxf_id_mask);
+	ll_req.rxf_id_mask[1] = bna_os_htonl((u32)(rxf_id_mask >> 32));
+	ll_req.enable = enable;
+
+	status = bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+	if (!status) {
+		if (enable)
+			dev->rxf_active |= rxf_id_mask;
+		else
+			dev->rxf_active &= ~rxf_id_mask;
+	}
+	return status;
+}
+
+/**
+ * bna_rxf_ucast_mac_set()
+ *
+ *  For RxF "rxf_id", it overwrites the burnt-in unicast MAC with
+ *  the one specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to mac adddress to set
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_ucast_mac_set(struct bna_dev_s *dev, unsigned int rxf_id,
+		       const u8 *mac_addr_ptr)
+{
+	struct bfi_ll_mac_addr_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	/* we are supposed to set MAC adresses for default RxF only */
+	if (dev->rxf_default_id == BNA_RXF_ID_NONE) {
+		if (rxf_id != BNA_DEFAULT_RXF_ID) {
+			DPRINTK(ERR,
+				"RxF Id [%d] Not Default RxF Id\n", rxf_id);
+			return BNA_FAIL;
+		}
+	} else {
+		if (rxf_id != dev->rxf_default_id) {
+			DPRINTK(ERR,
+			"RxF Id[%d] Not current Default RxF Id" "[%d]\n",
+				rxf_id, dev->rxf_default_id);
+			return BNA_FAIL;
+		}
+	}
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_UCAST_SET_REQ, 0);
+	cmd.rxf_id = rxf_id;
+	bna_os_memcpy(&cmd.mac_addr, mac_addr_ptr, sizeof(cmd.mac_addr));
+
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_rxf_ucast_mac_add()
+ *
+ *  For RxF "rxf_id", it adds the unicast MAC specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to mac adddress to add
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_ucast_mac_add(struct bna_dev_s *dev, unsigned int rxf_id,
+		       const u8 *mac_addr_ptr)
+{
+	struct bfi_ll_mac_addr_req cmd;
+
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+	/* we are not supposed to add MAC adresses to default RxF */
+	if (rxf_id == dev->rxf_default_id) {
+		DPRINTK(ERR,
+			"Cannot add MAC address for default RxF[%d]\n", rxf_id);
+		return BNA_FAIL;
+	}
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_UCAST_ADD_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	bna_os_memcpy(&cmd.mac_addr, mac_addr_ptr, sizeof(cmd.mac_addr));
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_rxf_ucast_mac_del()
+ *
+ *  For RxF "rxf_id", it deletes the unicast MAC specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to mac adddress to add
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_ucast_mac_del(struct bna_dev_s *dev, unsigned int rxf_id,
+		       const u8 *mac_addr_ptr)
+{
+	struct bfi_ll_mac_addr_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	/* we are not supposed to delete MAC adresses from default RxF */
+	if (rxf_id == dev->rxf_default_id) {
+		DPRINTK(ERR,
+			"Cannot del MAC address for default RxF[%d]\n", rxf_id);
+		return BNA_FAIL;
+	}
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_UCAST_DEL_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	bna_os_memcpy(&cmd.mac_addr, mac_addr_ptr, sizeof(cmd.mac_addr));
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_rxf_mcast_mac_add()
+ *
+ *  For RxF "rxf_id", it adds the multicast MAC specified by
+ *  "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to mac adddress to add
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_mcast_mac_add(struct bna_dev_s *dev, unsigned int rxf_id,
+		       const u8 *mac_addr_ptr)
+{
+	u32 mac_47_32, mac_31_0, i;
+	u8 *mac_ptr = (u8 *)mac_addr_ptr;
+	struct bfi_ll_mac_addr_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	mac_47_32 = (mac_ptr[0] << 8) | mac_ptr[1];
+	mac_31_0  = (mac_ptr[2] << 24) | (mac_ptr[3] << 16) |
+		    (mac_ptr[4] << 8) | mac_ptr[5];
+
+	for (i = 0; i < BNA_MCAST_TABLE_SIZE; i++) {
+		if ((mac_47_32 == dev->mcast_47_32[i]) &&
+		   (mac_31_0 == dev->mcast_31_0[i])) {
+			/* existing entry found, stop and use it */
+			break;
+		}
+	}
+
+	if (i == BNA_MCAST_TABLE_SIZE) {
+		/* no existing entry found we need to find the
+		first unused entry */
+		for (i = 0; i < BNA_MCAST_TABLE_SIZE; i++) {
+			if ((dev->mcast_47_32[i] == 0) &&
+			   (dev->mcast_31_0[i] == 0)) {
+				/* unused entry found, stop and use it */
+				break;
+			}
+		}
+	}
+
+	if (i == BNA_MCAST_TABLE_SIZE) {
+		/* no entry available, table full */
+		DPRINTK(ERR, "Multicast MAC table is full\n");
+		return BNA_FAIL;
+	}
+
+	dev->mcast_47_32[i] = mac_47_32;
+	dev->mcast_31_0[i] = mac_31_0;
+
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_MCAST_ADD_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	bna_os_memcpy(&cmd.mac_addr, mac_addr_ptr, sizeof(cmd.mac_addr));
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_rxf_mcast_mac_del()
+ *
+ *  For RxF "rxf_id", it deletes the multicast MAC specified by
+ *  "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to mac adddress to add
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_mcast_mac_del(struct bna_dev_s *dev, unsigned int rxf_id,
+		       const u8 *mac_addr_ptr)
+{
+	u32 mac_47_32, mac_31_0, i;
+	u8 *mac_ptr = (u8 *)mac_addr_ptr;
+	struct bfi_ll_mac_addr_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	mac_47_32 = (mac_ptr[0] << 8) | mac_ptr[1];
+	mac_31_0  = (mac_ptr[2] << 24) | (mac_ptr[3] << 16) |
+		    (mac_ptr[4] << 8) | mac_ptr[5];
+
+	for (i = 0; i < BNA_MCAST_TABLE_SIZE; i++) {
+		if ((mac_47_32 == dev->mcast_47_32[i]) &&
+		   (mac_31_0 == dev->mcast_31_0[i])) {
+			/* existing entry found, stop and use it */
+			break;
+		}
+	}
+
+	if (i == BNA_MCAST_TABLE_SIZE) {
+		/* no existing entry found */
+		DPRINTK(ERR, "MAC 0x%x:%x not found\n", mac_47_32, mac_31_0);
+		return BNA_FAIL;
+	}
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_MCAST_DEL_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	bna_os_memcpy(&cmd.mac_addr, mac_addr_ptr, sizeof(cmd.mac_addr));
+
+
+	dev->mcast_47_32[i] = 0;
+	dev->mcast_31_0[i] = 0;
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+static void
+bna_mac_addr_to_string(u32 mac_47_32, u32 mac_31_0, u8 *mac)
+{
+	u8 *mac_ptr = (u8 *)mac;
+	int i;
+
+	for (i = 1; i >= 0; i--)
+		mac_ptr[1-i] = ((mac_47_32) & (0xff << (i*8))) >> (i * 8);
+
+	mac_ptr = &mac_ptr[2];
+	for (i = 3; i >= 0; i--)
+		mac_ptr[3-i] = ((mac_31_0) & (0xff << (i*8))) >> (i * 8);
+}
+
+/**
+ * bna_rxf_mcast_mac_set_list()
+ *
+ *  For RxF "rxf_id", it sets the multicast MAC addresses
+ *  specified by "mac_addr_ptr". The function first deletes the MAC addresses in
+ *  the existing list that is not found in the new list. It then adds the new
+ *  addresses that are in the new list but not in the old list. It then replaces
+ *  the old list with the new list in the bna_dev structure.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to the list of mac
+ *       adddresses to set
+ * @param[in]  mac_addr_num - number of mac addresses in the
+ *       list
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_mcast_mac_set_list(struct bna_dev_s *dev, unsigned int rxf_id,
+			    const u8 *mac_addr_ptr ,
+			    unsigned int mac_addr_num)
+{
+	u32 *mcast_47_32 = &dev->tmp_mc_47_32[0];
+	u32 *mcast_31_0 = &dev->tmp_mc_31_0[0];
+	u32 i, j;
+	u8 *mac_ptr = (u8 *)mac_addr_ptr;
+	int found;
+	struct bfi_ll_mac_addr_req cmd;
+	u8 tmp_mac[ETH_ALEN];
+
+	bna_os_memset(mcast_47_32, 0, sizeof(u32) * BNA_MCAST_TABLE_SIZE);
+	bna_os_memset(mcast_31_0, 0, sizeof(u32) * BNA_MCAST_TABLE_SIZE);
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+	if (mac_addr_num > BNA_MCAST_TABLE_SIZE) {
+		DPRINTK(ERR,
+			"Too many Multicast Addresses [%d]\n", mac_addr_num);
+		return BNA_FAIL;
+	}
+
+	for (i = 0; i < mac_addr_num; i++) {
+		if (!BNA_MAC_IS_MULTICAST(mac_ptr[i * 6]))
+			return BNA_FAIL;
+		mcast_47_32[i] = (mac_ptr[i * 6] << 8) | mac_ptr[i * 6 + 1];
+		mcast_31_0[i] = (mac_ptr[i * 6 + 2] << 24) |
+				(mac_ptr[i * 6 + 3] << 16) |
+				(mac_ptr[i * 6 + 4] << 8) |
+				mac_ptr[i * 6 + 5];
+		if ((mcast_47_32[i] == 0) && (mcast_31_0[i] == 0))
+			return BNA_FAIL;
+		DPRINTK(DEBUG, "Multicast Addr %d : 0x%x:0x%x\n",
+			i, mcast_47_32[i], mcast_31_0[i]);
+	}
+
+	/* find MAC addresses to delete */
+	for (i = 0; i < BNA_MCAST_TABLE_SIZE; i++) {
+		if ((dev->mcast_47_32[i] == 0) && (dev->mcast_31_0[i] == 0))
+			continue;
+
+		found = 0;
+		for (j = 0; j < mac_addr_num; j++) {
+			if ((mcast_47_32[j] == dev->mcast_47_32[i]) &&
+			   (mcast_31_0[j] == dev->mcast_31_0[i])) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			bfi_h2i_set(cmd.mh, BFI_MC_LL,
+			     BFI_LL_H2I_MAC_MCAST_DEL_REQ, 0);
+			cmd.rxf_id = rxf_id;
+				bna_mac_addr_to_string(dev->mcast_47_32[i],
+						       dev->mcast_31_0[i],
+						       &tmp_mac[0]);
+				bna_os_memcpy(&cmd.mac_addr, &tmp_mac,
+					      sizeof(cmd.mac_addr));
+
+			DPRINTK(INFO,
+			"Deleting MCAST MAC 0x%x:0x%x on port %u RxF %u\n",
+				dev->mcast_47_32[i], dev->mcast_31_0[i],
+				dev->port, rxf_id);
+
+
+			if (BNA_FAIL == bna_mbox_send(dev, &cmd, sizeof(cmd),
+			    dev->cbarg)) {
+				DPRINTK(ERR,
+					"Failed to add to cmd [%d/%d] "
+					"for RxF %d to Q.. Aborting\n",
+					cmd.mh.msg_class, cmd.mh.msg_id,
+					cmd.rxf_id);
+				return BNA_FAIL;
+			}
+		}
+	}
+
+	/* find MAC addresses to add */
+	for (i = 0; i < mac_addr_num; i++) {
+		found = 0;
+
+		for (j = 0; j < BNA_MCAST_TABLE_SIZE; j++) {
+			if ((mcast_47_32[i] == dev->mcast_47_32[j]) &&
+			   (mcast_31_0[i] == dev->mcast_31_0[j])) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			bfi_h2i_set(cmd.mh, BFI_MC_LL,
+			     BFI_LL_H2I_MAC_MCAST_ADD_REQ, 0);
+			cmd.rxf_id = rxf_id;
+			bna_mac_addr_to_string(mcast_47_32[i],
+				mcast_31_0[i], &tmp_mac[0]);
+			bna_os_memcpy(&cmd.mac_addr, &tmp_mac,
+					      sizeof(cmd.mac_addr));
+
+			DPRINTK(INFO,
+			"Adding MCAST MAC 0x%x:0x%x on port %u RxF %u\n",
+				mcast_47_32[i], mcast_31_0[i],
+				dev->port, rxf_id);
+
+
+			if (BNA_FAIL == bna_mbox_send(dev, &cmd, sizeof(cmd),
+			    dev->cbarg)) {
+				DPRINTK(ERR,
+					"Failed to add to cmd [%d/%d] "
+					"for RxF %d to Q.. Aborting\n",
+					cmd.mh.msg_class, cmd.mh.msg_id,
+					cmd.rxf_id);
+				return BNA_FAIL;
+			}
+		}
+	}
+
+	bna_os_memset(&dev->mcast_47_32[0], 0, sizeof(u32) *
+		      BNA_MCAST_TABLE_SIZE);
+	bna_os_memset(&dev->mcast_31_0[0], 0, sizeof(u32) *
+		      BNA_MCAST_TABLE_SIZE);
+
+	bna_os_memcpy(&dev->mcast_47_32[0], &mcast_47_32[0],
+		      sizeof(u32) * mac_addr_num);
+	bna_os_memcpy(&dev->mcast_31_0[0],  &mcast_31_0[0],
+		      sizeof(u32) * mac_addr_num);
+
+	return BNA_OK;
+}
+
+/**
+ * bna_mcast_mac_reset_list()
+ *
+ *  Resets the multicast MAC address list kept by driver.
+ *  Called when the hw gets reset.
+ *
+ * @param[in]  dev  - pointer to BNA device structure
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_mcast_mac_reset_list(struct bna_dev_s *dev)
+{
+
+	bna_os_memset(&dev->mcast_47_32[0], 0, sizeof(u32) *
+	    BNA_MCAST_TABLE_SIZE);
+	bna_os_memset(&dev->mcast_31_0[0], 0, sizeof(u32) *
+	    BNA_MCAST_TABLE_SIZE);
+}
+
+/**
+ *  bna_rxf_broadcast()
+ *
+ *  For RxF "rxf_id", it enables/disables the broadcast address.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable broadcast address
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_broadcast(struct bna_dev_s *dev, unsigned int rxf_id,
+	enum bna_enable_e enable)
+{
+	const u8 broadcast_addr[ETH_ALEN] =
+		{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+	if (enable)
+		return bna_rxf_mcast_mac_add(dev, rxf_id, &broadcast_addr[0]);
+
+	return bna_rxf_mcast_mac_del(dev, rxf_id, &broadcast_addr[0]);
+}
+
+/**
+ *  bna_rxf_vlan_add()
+ *
+ *  For RxF "rxf_id", it adds this function as a member of the
+ *  specified "vlan_id".
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  vlan_id - VLAN id to be added
+ *
+ * @return void
+ */
+void bna_rxf_vlan_add(struct bna_dev_s *dev, unsigned int rxf_id,
+	unsigned int vlan_id)
+{
+
+	u32 new_vlan_id;
+
+	BNA_ASSERT((rxf_id <= BNA_RXF_ID_MAX));
+	/*
+	 * wrap the vlan_id around in case it
+	 * overflows the max limit
+	 */
+	new_vlan_id = vlan_id & BNA_VLAN_ID_MAX;
+	BNA_BIT_TABLE_SET(dev->vlan_table[rxf_id], new_vlan_id);
+
+	if (dev->vlan_filter_enable[rxf_id] &&
+	   (dev->rxf_active & ((u64)1 << rxf_id))) {
+		/* add VLAN ID on this function */
+		bna_reg_write(dev->regs.page_addr,
+			BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+						    (dev->port * 2),
+						    VLAN_RAM_BASE_OFFSET));
+		bna_mem_writew(BNA_GET_VLAN_MEM_ENTRY_ADDR(dev->bar0, rxf_id ,
+		    new_vlan_id), dev->vlan_table[rxf_id][new_vlan_id/32]);
+	}
+}
+
+/**
+ *  bna_rxf_vlan_del()
+ *
+ *  For RxF "rxf_id", it removes this function as a member of the
+ *  specified "vlan_id".
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  vlan_id - VLAN id to be removed
+ *
+ * @return void
+ */
+void bna_rxf_vlan_del(struct bna_dev_s *dev, unsigned int rxf_id,
+	unsigned int vlan_id)
+{
+
+	u32 new_vlan_id;
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	new_vlan_id = vlan_id & BNA_VLAN_ID_MAX;
+	BNA_BIT_TABLE_CLEAR(dev->vlan_table[rxf_id], new_vlan_id);
+
+	if (dev->vlan_filter_enable[rxf_id] &&
+		(dev->rxf_active & ((u64)1 << rxf_id))) {
+		bna_reg_write(dev->regs.page_addr,
+		BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+		    (dev->port * 2), VLAN_RAM_BASE_OFFSET));
+		bna_mem_writew(BNA_GET_VLAN_MEM_ENTRY_ADDR(dev->bar0, rxf_id ,
+		    new_vlan_id), dev->vlan_table[rxf_id][new_vlan_id/32]);
+	}
+}
+
+/**
+ *  bna_rxf_vlan_filter()
+ *
+ *   For RxF "rxf_id", it enables/disables the VLAN filter.
+ *   Disabling the VLAN Filter allows reception of any VLAN-tagged frame.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable VLAN Filtering.
+ *
+ * @return void
+ */
+void bna_rxf_vlan_filter(struct bna_dev_s *dev, unsigned int rxf_id,
+	enum bna_enable_e enable)
+{
+	u32 i;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	dev->vlan_filter_enable[rxf_id] = enable;
+
+	bna_reg_write(dev->regs.page_addr,
+		  BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+				VLAN_RAM_BASE_OFFSET));
+
+	if (enable) {
+		/* enable VLAN filtering on this function */
+		for (i = 0; i <= BNA_VLAN_ID_MAX/32; i++) {
+			bna_mem_writew(BNA_GET_VLAN_MEM_ENTRY_ADDR(dev->bar0,
+			    rxf_id, i * 32), dev->vlan_table[rxf_id][i]);
+		}
+	} else {
+		/* disable VLAN filtering on this function */
+		for (i = 0; i <= BNA_VLAN_ID_MAX/32; i++) {
+			bna_mem_writew(BNA_GET_VLAN_MEM_ENTRY_ADDR(dev->bar0,
+					rxf_id, i * 32), 0xffffffff);
+		}
+	}
+}
+
+/**
+ * bna_rxf_vlan_del_all()
+ *
+ *   For RxF "rxf_id", it clears all the VLANs.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ *
+ * @return void
+ */
+void
+bna_rxf_vlan_del_all(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	u32 i;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	bna_reg_write(dev->regs.page_addr,
+		  BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+				    VLAN_RAM_BASE_OFFSET));
+
+	/* clear all VLANs for this function */
+	for (i = 0; i <= BNA_VLAN_ID_MAX/32; i++) {
+		bna_mem_writew(BNA_GET_VLAN_MEM_ENTRY_ADDR(dev->bar0, rxf_id,
+		    i * 32), 0);
+	}
+}
+
+
+/**
+ *  bna_rxf_mcast_filter()
+ *
+ *   For RxF "rxf_id", it enables/disables the multicast filter.
+ *   Disabling the multicast filter allows reception of any
+ *   multicast frame.
+ *
+ * @param[in]  dev      - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable multicast Filtering.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_mcast_filter(struct bna_dev_s *dev,
+	unsigned int rxf_id, enum bna_enable_e enable)
+{
+
+	struct bfi_ll_mcast_filter_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_MCAST_FILTER_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	cmd.enable = enable;
+
+	/* send command to firmware*/
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_rxf_mcast_del_all()
+ *
+ *   For RxF "rxf_id", it clears the MCAST cam and MVT.
+ *   This functionality is required by some of the drivers.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_mcast_del_all(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	struct bfi_ll_mcast_del_all_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+
+	 /* send command to firmware*/
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ *  bna_rxf_promiscuous()
+ *
+ *  For RxF "rxf_id", it enables/disables promiscuous mode.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable promiscious mode
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_promiscuous(struct bna_dev_s *dev,
+	unsigned int rxf_id, enum bna_enable_e enable)
+{
+	struct bfi_ll_rxf_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	cmd.enable = enable;
+
+
+	/*
+	 * Need to revisit.
+	 * Can the second check be an ASSERT ?
+	 */
+	if (enable && (dev->rxf_promiscuous_id == BNA_RXF_ID_NONE)) {
+		dev->rxf_promiscuous_id = rxf_id;
+
+		/* allow all VLANs*/
+		bna_rxf_vlan_filter(dev, rxf_id, BNA_DISABLE);
+
+		return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+	} else if (!enable && (dev->rxf_promiscuous_id == rxf_id)) {
+		dev->rxf_promiscuous_id = BNA_RXF_ID_NONE;
+
+		/* Revert VLAN filtering */
+		bna_rxf_vlan_filter(dev, rxf_id,
+			dev->vlan_filter_enable[rxf_id]);
+
+		return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+	}
+
+	return BNA_FAIL;
+}
+
+/**
+ *  bna_rxf_default_mode()
+ *
+ *  For RxF "rxf_id", it enables/disables default mode.
+ *  Must be called after the RxF has been configured.
+ *  Must remove all unicast MAC associated to this RxF.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable default mode
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_default_mode(struct bna_dev_s *dev,
+	unsigned int rxf_id, enum bna_enable_e enable)
+{
+	struct bna_rx_fndb_ram *rx_fndb_ram;
+	u32 i, ctl_flags;
+	struct bfi_ll_rxf_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+
+	rx_fndb_ram = (struct bna_rx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, RX_FNDB_RAM_BASE_OFFSET);
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_RXF_DEFAULT_SET_REQ, 0);
+
+	cmd.rxf_id = rxf_id;
+	cmd.enable = enable;
+
+	/*
+	 * Need to revisit.
+	 * Can the second check be an ASSERT ?
+	 */
+	if (enable && (dev->rxf_default_id == BNA_RXF_ID_NONE)) {
+		dev->rxf_default_id = rxf_id;
+
+		/* allow all VLANs*/
+		bna_rxf_vlan_filter(dev, rxf_id, BNA_DISABLE);
+
+		bna_reg_write(dev->regs.page_addr,
+			BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+					  (dev->port * 2),
+					  RX_FNDB_RAM_BASE_OFFSET));
+
+		for (i = 0; i < BNA_RXF_ID_MAX; i++) {
+			if (i == rxf_id)
+				continue;
+
+			ctl_flags =
+				bna_mem_readw(&rx_fndb_ram[i].control_flags);
+			ctl_flags |= BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
+			bna_mem_writew(&rx_fndb_ram[i].control_flags,
+				ctl_flags);
+		}
+		return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+	} else if (!enable && (dev->rxf_default_id == rxf_id)) {
+		dev->rxf_default_id = BNA_RXF_ID_NONE;
+
+		/* Revert  VLAN filtering */
+		bna_rxf_vlan_filter(dev, rxf_id,
+			dev->vlan_filter_enable[rxf_id]);
+
+		bna_reg_write(dev->regs.page_addr,
+			BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+					  (dev->port * 2),
+					  RX_FNDB_RAM_BASE_OFFSET));
+
+		for (i = 0; i < BNA_RXF_ID_MAX; i++) {
+			ctl_flags =
+				bna_mem_readw(&rx_fndb_ram[i].control_flags);
+			ctl_flags &= ~BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
+			bna_mem_writew(&rx_fndb_ram[i].control_flags,
+				ctl_flags);
+		}
+		return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+	}
+
+	return BNA_FAIL;
+}
+
+/**
+ *  bna_rxf_frame_stats_get()
+ *
+ *  For RxF "rxf_id", it loads frame statistics into "stats_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[out]  stats_ptr - pointer to stats structure to fill
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_rxf_frame_stats_get(struct bna_dev_s *dev, unsigned int rxf_id,
+				  struct bna_stats_rxf **stats_ptr)
+{
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	*stats_ptr =  &dev->stats.rxf_stats[rxf_id];
+}
+
+/**
+ * bna_txf_frame_stats_get()
+ *
+ *   For TxF "txf_id", it loads frame statistics into "stats_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  txf_id    - tx-function ID.
+ * @param[out] stats_ptr - pointer to tx-function statistics.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_txf_frame_stats_get(struct bna_dev_s *dev, unsigned int txf_id,
+				  struct bna_stats_txf **stats_ptr)
+{
+
+	BNA_ASSERT(txf_id < BNA_TXF_ID_MAX);
+
+	*stats_ptr = &dev->stats.txf_stats[txf_id];
+}
+
+/**
+ *  bna_mac_rx_stats_get()
+ *
+ *  Loads MAC Rx statistics into "stats_ptr".
+ *
+ * @param[in]  dev       - pointer to BNA device structure
+
+ * @param[out]  stats_ptr - pointer to stats structure to fill
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_mac_rx_stats_get(struct bna_dev_s *dev, struct cna_stats_mac_rx **stats_ptr)
+{
+	*stats_ptr = &dev->stats.mac_rx_stats;
+}
+
+/**
+ *  bna_mac_tx_stats_get()
+ *
+ *  Loads MAC Tx statistics into "stats_ptr".
+ *
+ * @param[in]  dev       - pointer to BNA device structure
+
+ * @param[out]  stats_ptr - pointer to stats structure to fill
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_mac_tx_stats_get(struct bna_dev_s *dev, struct cna_stats_mac_tx **stats_ptr)
+{
+	*stats_ptr = &dev->stats.mac_tx_stats;
+}
+
+/**
+ *  bna_all_stats_get()
+ *
+ *  Loads all statistics into "stats_ptr".
+ *
+ * @param[in]  dev       - pointer to BNA device structure
+
+ * @param[out]  stats_ptr - pointer to stats structure
+ *
+ * @return void
+ */
+void
+bna_all_stats_get(struct bna_dev_s *dev, struct bna_stats **stats_ptr)
+{
+	*stats_ptr = &dev->stats;
+}
+
+/**
+ * bna_stats_get()
+ *
+ *   Get the statistics from the device. This function needs to
+ *   be scheduled every second to get periodic update of the
+ *   statistics data from hardware.
+ *
+ * @param[in]   dev       - pointer to BNA device structure.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_stats_get(struct bna_dev_s *dev)
+{
+	struct bfi_ll_stats_req cmd;
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0);
+
+	cmd.stats_mask    = bna_os_htons(BFI_LL_STATS_ALL);
+	cmd.rxf_id_mask[0]  = bna_os_htonl(
+				(u32)(dev->rxf_active & 0xffffffff));
+	cmd.rxf_id_mask[1]  = bna_os_htonl(
+				(u32)(dev->rxf_active >> 32));
+
+	cmd.txf_id_mask[0]  = bna_os_htonl(
+				(u32)(dev->txf_active & 0xffffffff));
+	cmd.txf_id_mask[1]  = bna_os_htonl((u32)(dev->txf_active >> 32));
+
+	cmd.host_buffer.a32.addr_hi = dev->hw_stats_dma.msb;
+	cmd.host_buffer.a32.addr_lo = dev->hw_stats_dma.lsb;
+
+	dev->rxf_active_last = dev->rxf_active;
+	dev->txf_active_last = dev->txf_active;
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_stats_clear()
+ *
+ *   Clear the statistics in the device.
+ *
+ * @param[in]   dev       - pointer to BNA device structure.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_stats_clear(struct bna_dev_s *dev)
+{
+	struct bfi_ll_stats_req cmd;
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
+
+	cmd.stats_mask = bna_os_htons(BFI_LL_STATS_ALL);
+	cmd.rxf_id_mask[0] = bna_os_htonl(
+				(u32)(dev->rxf_active & 0xffffffff));
+	cmd.rxf_id_mask[1] = bna_os_htonl((u32)(dev->rxf_active >> 32));
+
+	cmd.txf_id_mask[0] = bna_os_htonl(
+				(u32)(dev->txf_active & 0xffffffff));
+	cmd.txf_id_mask[1] = bna_os_htonl((u32)(dev->txf_active >> 32));
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+/**
+ * bna_rxf_stats_clear()
+ *
+ *   Clear the statistics for specified txf.
+ *
+ * @param[in]   dev        - pointer to BNA device structure.
+ * @param[in]  rxf_id      - rx-function ID.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_stats_clear(struct bna_dev_s *dev, unsigned int rxf_id)
+{
+	struct bfi_ll_stats_req cmd;
+
+	BNA_ASSERT(rxf_id < BNA_RXF_ID_MAX);
+
+	bfi_h2i_set(cmd.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
+
+	cmd.stats_mask = 0;
+
+	if (rxf_id < 32) {
+		cmd.rxf_id_mask[0] = bna_os_htonl((u32)(1 << rxf_id));
+		cmd.rxf_id_mask[1] = 0;
+	} else {
+		cmd.rxf_id_mask[0] = 0;
+		cmd.rxf_id_mask[1] = bna_os_htonl(
+					(u32)(1 << (rxf_id - 32)));
+	}
+
+	cmd.txf_id_mask[0] = 0;
+	cmd.txf_id_mask[1] = 0;
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_lldp_stats_clear()
+ *
+ *   Clear the DCBCX-LLDP statistics in the f/w.
+ *
+ * @param[in]   dev       - pointer to BNA device structure.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_lldp_stats_clear(struct bna_dev_s *dev)
+{
+	struct bfi_lldp_reset_stats_s cmd;
+
+	bfi_h2i_set(cmd.mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, 0);
+
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_get_cfg_req()
+ *
+ *   Request to get the LLDP-DCBCX Config.
+ *
+ * @param[in]   dev       - pointer to BNA device structure.
+ * @param[in]   dma_ddr   - dma address in "bna_dma_addr_t" format.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_get_cfg_req(struct bna_dev_s *dev, struct bna_dma_addr *dma_addr)
+{
+	struct bfi_cee_get_req_s cmd;
+
+	bfi_h2i_set(cmd.mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, 0);
+	cmd.dma_addr.a32.addr_lo = dma_addr->lsb;
+	cmd.dma_addr.a32.addr_hi = dma_addr->msb;
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_get_cee_stats_req()
+ *
+ *   Request to get the LLDP-DCBCX stats.
+ *
+ * @param[in]   dev       - pointer to BNA device structure.
+ * @param[in]   dma_ddr   - dma address in "bna_dma_addr_t" format.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_get_cee_stats_req(struct bna_dev_s *dev, struct bna_dma_addr *dma_addr)
+{
+	struct bfi_cee_get_req_s cmd;
+
+	bfi_h2i_set(cmd.mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, 0);
+	cmd.dma_addr.a32.addr_lo = dma_addr->lsb;
+	cmd.dma_addr.a32.addr_hi = dma_addr->msb;
+	/* send command to firmware */
+	return bna_mbox_send(dev, &cmd, sizeof(cmd), dev->cbarg);
+}
+
+/**
+ * bna_stats_process()
+ *
+ *   Process the statistics data DMAed from the device. This
+ *   function needs to be scheduled upon getting an asynchronous
+ *   notification from the firmware.
+ *
+ * @param[in]   dev       - pointer to BNA device structure.
+ *
+ * @return void
+ */
+void
+bna_stats_process(struct bna_dev_s *dev)
+{
+	u32 i, j;
+	struct bna_stats_rxf *rxf_hw_stats;
+	struct bna_stats_txf *txf_hw_stats;
+
+	dev->stats.fc_tx_stats.txf_ucast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_ucast_octets);
+	dev->stats.fc_tx_stats.txf_ucast	= bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_ucast);
+	dev->stats.fc_tx_stats.txf_ucast_vlan   = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_ucast_vlan);
+
+	dev->stats.fc_tx_stats.txf_mcast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_mcast_octets);
+	dev->stats.fc_tx_stats.txf_mcast	= bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_mcast);
+	dev->stats.fc_tx_stats.txf_mcast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_mcast_vlan);
+
+	dev->stats.fc_tx_stats.txf_bcast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_bcast_octets);
+	dev->stats.fc_tx_stats.txf_bcast = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_bcast);
+	dev->stats.fc_tx_stats.txf_bcast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_bcast_vlan);
+
+	dev->stats.fc_tx_stats.txf_parity_errors = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_parity_errors);
+	dev->stats.fc_tx_stats.txf_timeout = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_timeout);
+	dev->stats.fc_tx_stats.txf_fid_parity_errors = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_tx_stats.txf_fid_parity_errors);
+
+	for (i = 0; i < 8; i++) {
+		dev->stats.bpc_tx_stats.tx_pause[i] = bna_hw_stats_to_stats(
+			dev->hw_stats->bpc_stats.tx_pause[i]);
+		dev->stats.bpc_tx_stats.tx_zero_pause[i] =
+			bna_hw_stats_to_stats(
+			dev->hw_stats->bpc_stats.tx_zero_pause[i]);
+		dev->stats.bpc_tx_stats.tx_first_pause[i] =
+			bna_hw_stats_to_stats(
+			dev->hw_stats->bpc_stats.tx_first_pause[i]);
+	}
+
+	dev->stats.mac_tx_stats.tx_bytes = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_bytes);
+	dev->stats.mac_tx_stats.tx_packets = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_packets);
+	dev->stats.mac_tx_stats.tx_multicast = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_multicast);
+	dev->stats.mac_tx_stats.tx_broadcast = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_broadcast);
+	dev->stats.mac_tx_stats.tx_pause = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_pause);
+	dev->stats.mac_tx_stats.tx_deferral = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_deferral);
+	dev->stats.mac_tx_stats.tx_excessive_deferral = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_excessive_deferral);
+	dev->stats.mac_tx_stats.tx_single_collision = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_single_collision);
+	dev->stats.mac_tx_stats.tx_muliple_collision = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_muliple_collision);
+	dev->stats.mac_tx_stats.tx_late_collision = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_late_collision);
+	dev->stats.mac_tx_stats.tx_excessive_collision = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_excessive_collision);
+	dev->stats.mac_tx_stats.tx_total_collision = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_total_collision);
+	dev->stats.mac_tx_stats.tx_pause_honored = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_pause_honored);
+	dev->stats.mac_tx_stats.tx_drop	= bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_drop);
+	dev->stats.mac_tx_stats.tx_jabber = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_jabber);
+	dev->stats.mac_tx_stats.tx_fcs_error = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_fcs_error);
+	dev->stats.mac_tx_stats.tx_control_frame = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_control_frame);
+	dev->stats.mac_tx_stats.tx_oversize = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_oversize);
+	dev->stats.mac_tx_stats.tx_undersize = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_undersize);
+	dev->stats.mac_tx_stats.tx_fragments = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.tx_fragments);
+
+	dev->stats.fc_rx_stats.rxf_ucast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_ucast_octets);
+	dev->stats.fc_rx_stats.rxf_ucast = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_ucast);
+	dev->stats.fc_rx_stats.rxf_ucast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_ucast_vlan);
+
+	dev->stats.fc_rx_stats.rxf_mcast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_mcast_octets);
+	dev->stats.fc_rx_stats.rxf_mcast = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_mcast);
+	dev->stats.fc_rx_stats.rxf_mcast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_mcast_vlan);
+
+	dev->stats.fc_rx_stats.rxf_bcast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_bcast_octets);
+	dev->stats.fc_rx_stats.rxf_bcast = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_bcast);
+	dev->stats.fc_rx_stats.rxf_bcast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->fc_rx_stats.rxf_bcast_vlan);
+
+	for (i = 0; i < 8; i++) {
+		dev->stats.bpc_rx_stats.rx_pause[i] = bna_hw_stats_to_stats(
+			dev->hw_stats->bpc_stats.rx_pause[i]);
+		dev->stats.bpc_rx_stats.rx_zero_pause[i] =
+			bna_hw_stats_to_stats(
+			dev->hw_stats->bpc_stats.rx_zero_pause[i]);
+		dev->stats.bpc_rx_stats.rx_first_pause[i] =
+			bna_hw_stats_to_stats(
+			dev->hw_stats->bpc_stats.rx_first_pause[i]);
+	}
+
+	dev->stats.rad_stats.rx_frames = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_frames);
+	dev->stats.rad_stats.rx_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_octets);
+	dev->stats.rad_stats.rx_vlan_frames = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_vlan_frames);
+
+	dev->stats.rad_stats.rx_ucast = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_ucast);
+	dev->stats.rad_stats.rx_ucast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_ucast_octets);
+	dev->stats.rad_stats.rx_ucast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_ucast_vlan);
+
+	dev->stats.rad_stats.rx_mcast = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_mcast);
+	dev->stats.rad_stats.rx_mcast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_mcast_octets);
+	dev->stats.rad_stats.rx_mcast_vlan = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_mcast_vlan);
+
+	dev->stats.rad_stats.rx_bcast = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_bcast);
+	dev->stats.rad_stats.rx_bcast_octets = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_bcast_octets);
+	dev->stats.rad_stats.rx_bcast_vlan      = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_bcast_vlan);
+
+	dev->stats.rad_stats.rx_drops = bna_hw_stats_to_stats(
+		dev->hw_stats->rad_stats.rx_drops);
+
+	dev->stats.mac_rx_stats.frame_64 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_64);
+	dev->stats.mac_rx_stats.frame_65_127 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_65_127);
+	dev->stats.mac_rx_stats.frame_128_255 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_128_255);
+	dev->stats.mac_rx_stats.frame_256_511 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_256_511);
+	dev->stats.mac_rx_stats.frame_512_1023 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_512_1023);
+	dev->stats.mac_rx_stats.frame_1024_1518 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_1024_1518);
+	dev->stats.mac_rx_stats.frame_1518_1522 = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.frame_1519_1522);
+	dev->stats.mac_rx_stats.rx_bytes = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_bytes);
+	dev->stats.mac_rx_stats.rx_packets = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_packets);
+	dev->stats.mac_rx_stats.rx_fcs_error = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_fcs_error);
+	dev->stats.mac_rx_stats.rx_multicast = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_multicast);
+	dev->stats.mac_rx_stats.rx_broadcast = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_broadcast);
+	dev->stats.mac_rx_stats.rx_control_frames = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_control_frames);
+	dev->stats.mac_rx_stats.rx_pause = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_pause);
+	dev->stats.mac_rx_stats.rx_unknown_opcode = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_unknown_opcode);
+	dev->stats.mac_rx_stats.rx_alignment_error = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_alignment_error);
+	dev->stats.mac_rx_stats.rx_frame_length_error = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_frame_length_error);
+	dev->stats.mac_rx_stats.rx_code_error = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_code_error);
+	dev->stats.mac_rx_stats.rx_carrier_sense_error = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_carrier_sense_error);
+	dev->stats.mac_rx_stats.rx_undersize = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_undersize);
+	dev->stats.mac_rx_stats.rx_oversize = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_oversize);
+	dev->stats.mac_rx_stats.rx_fragments = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_jabber);
+	dev->stats.mac_rx_stats.rx_jabber = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_jabber);
+	dev->stats.mac_rx_stats.rx_drop = bna_hw_stats_to_stats(
+		dev->hw_stats->mac_stats.rx_drop);
+
+	rxf_hw_stats = (struct bna_stats_rxf *)&dev->hw_stats->rxf_stats[0];
+	j = 0;
+
+	for (i = 0; i < BNA_RXF_ID_MAX; i++) {
+		if (dev->rxf_active_last & ((u64)1 << i)) {
+			dev->stats.rxf_stats[i].ucast_octets =
+				bna_hw_stats_to_stats(
+				rxf_hw_stats[j].ucast_octets);
+		dev->stats.rxf_stats[i].ucast = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].ucast);
+		dev->stats.rxf_stats[i].ucast_vlan = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].ucast_vlan);
+
+		dev->stats.rxf_stats[i].mcast_octets = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].mcast_octets);
+		dev->stats.rxf_stats[i].mcast = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].mcast);
+		dev->stats.rxf_stats[i].mcast_vlan = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].mcast_vlan);
+
+		dev->stats.rxf_stats[i].bcast_octets = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].bcast_octets);
+		dev->stats.rxf_stats[i].bcast = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].bcast);
+		dev->stats.rxf_stats[i].bcast_vlan = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].bcast_vlan);
+
+		dev->stats.rxf_stats[i].frame_drops = bna_hw_stats_to_stats(
+			rxf_hw_stats[j].frame_drops);
+
+		j++;
+		}
+	}
+
+	txf_hw_stats = (struct bna_stats_txf *)&rxf_hw_stats[j];
+	j = 0;
+
+	for (i = 0; i < BNA_TXF_ID_MAX; i++) {
+		if (dev->txf_active_last & ((u64)1 << i)) {
+			dev->stats.txf_stats[i].ucast_octets =
+				bna_hw_stats_to_stats(
+				txf_hw_stats[j].ucast_octets);
+		dev->stats.txf_stats[i].ucast = bna_hw_stats_to_stats(
+			txf_hw_stats[j].ucast);
+		dev->stats.txf_stats[i].ucast_vlan = bna_hw_stats_to_stats(
+			txf_hw_stats[j].ucast_vlan);
+
+		dev->stats.txf_stats[i].mcast_octets = bna_hw_stats_to_stats(
+			txf_hw_stats[j].mcast_octets);
+		dev->stats.txf_stats[i].mcast = bna_hw_stats_to_stats(
+			txf_hw_stats[j].mcast);
+		dev->stats.txf_stats[i].mcast_vlan = bna_hw_stats_to_stats(
+			txf_hw_stats[j].mcast_vlan);
+
+		dev->stats.txf_stats[i].bcast_octets = bna_hw_stats_to_stats(
+			txf_hw_stats[j].bcast_octets);
+		dev->stats.txf_stats[i].bcast = bna_hw_stats_to_stats(
+			txf_hw_stats[j].bcast);
+		dev->stats.txf_stats[i].bcast_vlan = bna_hw_stats_to_stats(
+			txf_hw_stats[j].bcast_vlan);
+
+		dev->stats.txf_stats[i].errors = bna_hw_stats_to_stats(
+			txf_hw_stats[j].errors);
+		dev->stats.txf_stats[i].filter_vlan = bna_hw_stats_to_stats(
+			txf_hw_stats[j].filter_vlan);
+		dev->stats.txf_stats[i].filter_mac_sa = bna_hw_stats_to_stats(
+			txf_hw_stats[j].filter_mac_sa);
+
+		j++;
+	}
+    }
+}
+
+/**
+ * bna_txf_config_set()
+ *
+ *   For TxF "txf_id", it configures the TxF specified by "cfg_ptr" and
+ *   indicates to the statistics collector to collect statistics for this
+ *   Tx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  txf_id  - tx-function ID.
+ * @param[in]  cfg_ptr - pointer to tx-function configuration.
+ *
+ * @return void
+ */
+void
+bna_txf_config_set(struct bna_dev_s *dev, unsigned int txf_id,
+		    const struct bna_txf_config *cfg_ptr)
+{
+
+	struct bna_tx_fndb_ram *tx_fndb;
+
+	BNA_ASSERT(txf_id < BNA_TXF_ID_MAX);
+
+	tx_fndb = (struct bna_tx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, TX_FNDB_RAM_BASE_OFFSET);
+
+	bna_reg_write(dev->regs.page_addr, BNA_GET_PAGE_NUM(
+		LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+		TX_FNDB_RAM_BASE_OFFSET));
+
+	bna_mem_writew(&tx_fndb[txf_id],
+		       (cfg_ptr->vlan << 16) | cfg_ptr->flags);
+
+	/* turn on statistics collection */
+	dev->txf_active |= ((u64)1 << txf_id);
+}
+
+/**
+ * bna_txf_config_clear()
+ *
+ *   For TxF "txf_id", it clears its configuration and indicates to the
+ *   statistics collector to stop collecting statistics for this
+ *   Tx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  txf_id  - tx-function ID.
+ *
+ * @return void
+ */
+void
+bna_txf_config_clear(struct bna_dev_s *dev, unsigned int txf_id)
+{
+
+	struct bna_tx_fndb_ram *tx_fndb;
+
+	BNA_ASSERT(txf_id < BNA_TXF_ID_MAX);
+
+	tx_fndb = (struct bna_tx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, TX_FNDB_RAM_BASE_OFFSET);
+
+	bna_reg_write(dev->regs.page_addr,
+		BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+				  TX_FNDB_RAM_BASE_OFFSET));
+
+	bna_mem_writew(&tx_fndb[txf_id], 0);
+
+	/* turn off statistics collection */
+	dev->txf_active &= ~((u64)1 << txf_id);
+}
+
+/**
+ * bna_txf_disable()
+ *
+ *  Disables the Tx Function without clearing the configuration
+ *  Also disables collection of statistics.
+ *
+ * @param[in] bna_dev   - Pointer to BNA device handle
+ * @param[in] txf_id    - Id of the Tx Function to be disabled
+ *
+ * @return void
+ */
+void
+bna_txf_disable(struct bna_dev_s *dev, unsigned int txf_id)
+{
+	struct bna_tx_fndb_ram *tx_fndb;
+	u32 page_num, ctl_flags;
+
+	BNA_ASSERT(txf_id < BNA_TXF_ID_MAX);
+
+	tx_fndb = (struct bna_tx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, TX_FNDB_RAM_BASE_OFFSET);
+
+	/* Write the page number register */
+	page_num =
+	    BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM + (dev->port * 2),
+	    TX_FNDB_RAM_BASE_OFFSET);
+	bna_reg_write(dev->regs.page_addr, page_num);
+
+	ctl_flags = bna_mem_readw(&tx_fndb[txf_id].vlan_n_ctrl_flags);
+
+	ctl_flags &= ~BNA_TXF_CF_ENABLE;
+
+	bna_mem_writew(&tx_fndb[txf_id].vlan_n_ctrl_flags, ctl_flags);
+
+	/* turn off statistics collection */
+	dev->txf_active &= ~((u64)1 << txf_id);
+}
+
+/**
+ * bna_txf_enable()
+ *
+ *  Enables the Tx Function without reconfiguring.
+ *  Also disables collection of statistics.
+ *
+ * @param[in] bna_dev   - Pointer to BNA device handle
+ * @param[in] txf_id    - Id of the Tx Function to be disabled
+ *
+ * @return void
+ */
+void
+bna_txf_enable(struct bna_dev_s *dev, unsigned int txf_id)
+{
+	struct bna_tx_fndb_ram *tx_fndb;
+	u32 page_num, ctl_flags;
+
+	BNA_ASSERT(txf_id < BNA_TXF_ID_MAX);
+
+	tx_fndb = (struct bna_tx_fndb_ram *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, TX_FNDB_RAM_BASE_OFFSET);
+
+	/* Write the page number register */
+	page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+	    (dev->port * 2), TX_FNDB_RAM_BASE_OFFSET);
+	bna_reg_write(dev->regs.page_addr, page_num);
+
+	ctl_flags = bna_mem_readw(&tx_fndb[txf_id].vlan_n_ctrl_flags);
+
+	ctl_flags |= BNA_TXF_CF_ENABLE;
+
+	bna_mem_writew(&tx_fndb[txf_id].vlan_n_ctrl_flags, ctl_flags);
+
+	/* turn on statistics collection */
+	dev->txf_active |= ((u64)1 << txf_id);
+}
+
+/**
+ * bna_set_pause_config()
+ *
+ *   Enable/disable Tx/Rx pause through F/W
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure
+ * @param[in]   pause 	  - pointer to struct bna_pause_config
+ *
+ * @return BNA_OK in case of success BNA_FAIL otherwise.
+ */
+enum bna_status_e
+bna_set_pause_config(struct bna_dev_s *dev, struct bna_pause_config *pause,
+    void *cbarg)
+{
+	struct bfi_ll_set_pause_req ll_req;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_SET_PAUSE_REQ, 0);
+
+	ll_req.tx_pause = pause->tx_pause;
+	ll_req.rx_pause = pause->rx_pause;
+
+	DPRINTK(INFO, "Port %d tx_pause %d rx_pause %d\n",
+		dev->port, ll_req.tx_pause, ll_req.rx_pause);
+
+	/* send to f/w */
+	return bna_mbox_send(dev, &ll_req, sizeof(ll_req), cbarg);
+}
+
+/**
+ * bna_mtu_info()
+ *
+ *   Send MTU information to F/W.
+ *   This is required to do PAUSE efficiently.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure
+ * @param[in]   mtu	  - current mtu size
+ * @param[in]   cbarg	  - argument for the callback function
+ *
+ * @return BNA_OK in case of success BNA_FAIL otherwise.
+ */
+enum bna_status_e
+bna_mtu_info(struct bna_dev_s *dev, u16 mtu, void *cbarg)
+{
+	struct bfi_ll_mtu_info_req ll_req;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0);
+	ll_req.mtu      = bna_os_htons(mtu);
+
+	DPRINTK(INFO, "Port %d MTU %d\n", dev->port, mtu);
+
+	/* send to f/w */
+	return bna_mbox_send(dev, &ll_req, sizeof(ll_req), cbarg);
+}
+
+/* Currently we assume just 2 columns, col 0 = small, col 1 = large */
+u32 intr_mod_vector[BNA_LOAD_TYPES + 1][BNA_BIAS_TYPES] = {
+		{ 12,  12 },
+		{  6,  10 },
+		{  5,  10 },
+		{  4,   8 },
+		{  3,   6 },
+		{  3,   6 },
+		{  2,   4 },
+		{  1,   2 },
+	};
+
+/**
+ * Returns the coalescing timer value
+ */
+u8
+bna_calc_coalescing_timer(struct bna_dev_s *dev, struct bna_pkt_rate *pkt)
+{
+	u32 load, bias;
+	u32 pkt_rt = 0, small_rt, large_rt;
+
+
+	small_rt = pkt->small_pkt_cnt;
+	large_rt = pkt->large_pkt_cnt;
+
+	pkt_rt = small_rt + large_rt;
+
+	if (pkt_rt < BNA_10K_PKT_RATE)
+		load = BNA_LOW_LOAD_4;
+	else if (pkt_rt < BNA_20K_PKT_RATE)
+		load = BNA_LOW_LOAD_3;
+	else if (pkt_rt < BNA_30K_PKT_RATE)
+		load = BNA_LOW_LOAD_2;
+	else if (pkt_rt < BNA_40K_PKT_RATE)
+		load = BNA_LOW_LOAD_1;
+	else if (pkt_rt < BNA_50K_PKT_RATE)
+		load = BNA_HIGH_LOAD_1;
+	else if (pkt_rt < BNA_60K_PKT_RATE)
+		load = BNA_HIGH_LOAD_2;
+	else if (pkt_rt < BNA_80K_PKT_RATE)
+		load = BNA_HIGH_LOAD_3;
+	else
+		load = BNA_HIGH_LOAD_4;
+
+
+	if (small_rt > (large_rt << 1))
+		bias = 0;
+	else
+		bias = 1;
+
+	pkt->small_pkt_cnt = pkt->large_pkt_cnt = 0;
+	return intr_mod_vector[load][bias];
+}
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_queue.c net-next-2.6-mod/drivers/net/bna/bna_queue.c
--- net-next-2.6-orig/drivers/net/bna/bna_queue.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_queue.c	2009-10-31 21:34:47.682533000 -0700
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ *    Copyright (c) 2007-2008 Brocade Communications Systems, Inc.
+ *    All rights reserved.
+ *
+ *    @file bna_queue.c BNA Queues
+ */
+
+#include <bna_os.h>
+#include "bna.h"
+#include "bna_hwreg.h"
+#include "bna_priv.h"
+#include <bfi/bfi_ll.h>
+
+
+#define BNA_Q_IDLE_STATE	0x00008001
+/*
+ *-----------------------------------------------------------------------------
+ *  bna_txq_config()
+ *
+ *  For TxQ "txq_id", it configures the Tx-Queue as specified by "cfg_ptr".
+ *-----------------------------------------------------------------------------
+ */
+void bna_txq_config(struct bna_dev_s *dev, struct bna_txq *q_ptr,
+	unsigned int txq_id, const struct bna_txq_config *cfg_ptr)
+{
+	struct bna_rxtx_q_mem *q_mem;
+	struct bna_txq_mem txq_cfg, *txq_mem;
+	const struct bna_qpt *qpt = &cfg_ptr->qpt;
+	struct bna_dma_addr cur_q_addr;
+	struct bna_doorbell_qset *qset;
+	u32 pg_num;
+
+	BNA_ASSERT(txq_id < BNA_TXQ_ID_MAX);
+	/* Check if the depth is a power of 2 */
+	BNA_ASSERT(BNA_POWER_OF_2(q_ptr->q.q_depth));
+
+
+	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+
+	/*
+	 * Fill out structure, to be subsequently written
+	 * to hardware
+	 */
+	txq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+	txq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+
+	/* FIXME */
+	txq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+	txq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+	txq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
+
+	/* Is the entry size in words ? Check */
+	txq_cfg.entry_n_pg_size = ((BNA_TXQ_ENTRY_SIZE >> 2) << 16) |
+		(qpt->page_size >> 2);
+	txq_cfg.int_blk_n_cns_ptr =
+		((((u8)cfg_ptr->ib_seg_index) << 24) |
+		(((u8)cfg_ptr->ib_id) << 16) | 0x0);
+	txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
+	txq_cfg.nxt_qid_n_fid_n_pri = (((cfg_ptr->txf_id
+		& 0x3f) << 3) | (cfg_ptr->priority & 0x3));
+	txq_cfg.wvc_n_cquota_n_rquota = (((cfg_ptr->wrr_quota & 0xfff) << 12) |
+		(cfg_ptr->wrr_quota & 0xfff));
+
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + dev->port,
+		HQM_RXTX_Q_RAM_BASE_OFFSET);
+
+	bna_reg_write(dev->regs.page_addr, pg_num);
+	/* Write to h/w */
+	q_mem = (struct bna_rxtx_q_mem *)
+	BNA_GET_MEM_BASE_ADDR(dev->bar0, HQM_RXTX_Q_RAM_BASE_OFFSET);
+
+	txq_mem = &q_mem[txq_id].txq;
+
+	/*
+	 * The following 4 lines, is a hack b'cos the H/W needs to read
+	 * these DMA addresses as little endian
+	 */
+	bna_mem_writew(&txq_mem->pg_tbl_addr_lo,
+					bna_os_htonl(txq_cfg.pg_tbl_addr_lo));
+	bna_mem_writew(&txq_mem->pg_tbl_addr_hi,
+					bna_os_htonl(txq_cfg.pg_tbl_addr_hi));
+	bna_mem_writew(&txq_mem->cur_q_entry_lo,
+					 bna_os_htonl(txq_cfg.cur_q_entry_lo));
+	bna_mem_writew(&txq_mem->cur_q_entry_hi,
+					 bna_os_htonl(txq_cfg.cur_q_entry_hi));
+
+	bna_mem_writew(&txq_mem->pg_cnt_n_prd_ptr, txq_cfg.pg_cnt_n_prd_ptr);
+	bna_mem_writew(&txq_mem->entry_n_pg_size, txq_cfg.entry_n_pg_size);
+	bna_mem_writew(&txq_mem->int_blk_n_cns_ptr,
+	txq_cfg.int_blk_n_cns_ptr);
+	bna_mem_writew(&txq_mem->cns_ptr2_n_q_state,
+	txq_cfg.cns_ptr2_n_q_state);
+	bna_mem_writew(&txq_mem->nxt_qid_n_fid_n_pri,
+	txq_cfg.nxt_qid_n_fid_n_pri);
+	bna_mem_writew(&txq_mem->wvc_n_cquota_n_rquota,
+	txq_cfg.wvc_n_cquota_n_rquota);
+
+	DPRINTK(DEBUG, "TxQ %u\n", txq_id);
+	DPRINTK(DEBUG, "TxQ pg_tbl_addr_lo 0x%x\n",
+		bna_os_ntohl(txq_cfg.pg_tbl_addr_lo));
+	DPRINTK(DEBUG, "TxQ cur_q_entry_lo 0x%x\n",
+		bna_os_ntohl(txq_cfg.cur_q_entry_lo));
+	DPRINTK(DEBUG, "TxQ pg_cnt_n_prd_ptr 0x%x\n",
+		txq_cfg.pg_cnt_n_prd_ptr);
+	DPRINTK(DEBUG, "TxQ entry_n_pg_size 0x%x\n",
+		txq_cfg.entry_n_pg_size);
+	DPRINTK(DEBUG, "TxQ int_blk_n_cns_ptr 0x%x\n",
+		txq_cfg.int_blk_n_cns_ptr);
+	DPRINTK(DEBUG, "TxQ cns_ptr2_n_q_state 0x%x\n",
+		txq_cfg.cns_ptr2_n_q_state);
+	DPRINTK(DEBUG, "TxQ nxt_qid_n_fid_n_pri 0x%x\n",
+		txq_cfg.nxt_qid_n_fid_n_pri);
+	DPRINTK(DEBUG, "TxQ wvc_n_cquota_n_rquota 0x%x\n",
+		txq_cfg.wvc_n_cquota_n_rquota);
+
+	qset = (struct bna_doorbell_qset *)
+		BNA_GET_DOORBELL_BASE_ADDR(dev->bar0);
+	q_ptr->doorbell =  &qset[txq_id].txq[0];
+
+	q_ptr->q.producer_index = 0;
+	q_ptr->q.consumer_index = 0;
+}
+
+
+/**
+ * bna_txq_stop()
+ *
+ * 	Stops the TxQ identified by the TxQ Id.
+ *	Should be called with a lock held
+ *	The driver should wait for the response to
+ *	conclude if the Q stop is successful or not.
+ *
+ * @param[in] q_id	- Id of the TxQ
+ *
+ * @return    BNA_OK in case of success, else BNA_FAIL
+ */
+enum bna_status_e
+bna_txq_stop(struct bna_dev_s *dev, u32 txq_id)
+{
+	struct bfi_ll_q_stop_req ll_req;
+	u64 bit_mask = 1 << txq_id;
+
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ;
+	ll_req.mh.mtag.i2htok = 0;
+
+	ll_req.q_id_mask[0] = bna_os_htonl((u32)bit_mask);
+	ll_req.q_id_mask[1] = bna_os_htonl((u32)(bit_mask >> 32));
+
+	/* send to f/w */
+	return bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *  bna_rxq_config()
+ *
+ *  For RxQ "rxq_id", it configures the Rx-Queue as specified by "cfg_ptr".
+ *-----------------------------------------------------------------------------
+ */
+void
+bna_rxq_config(struct bna_dev_s *dev, struct bna_rxq *q_ptr,
+    unsigned int rxq_id, const struct bna_rxq_config *cfg_ptr)
+{
+	struct bna_rxtx_q_mem *q_mem;
+	struct bna_rxq_mem rxq_cfg, *rxq_mem;
+	const struct bna_qpt *qpt = &cfg_ptr->qpt;
+	struct bna_dma_addr cur_q_addr;
+	struct bna_doorbell_qset *qset;
+	u32 pg_num;
+
+	BNA_ASSERT(rxq_id < BNA_RXQ_ID_MAX);
+
+	/* Check if the depth is a power of 2 */
+	BNA_ASSERT(BNA_POWER_OF_2(q_ptr->q.q_depth));
+
+
+	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+	/*
+	 * Fill out structure, to be subsequently written
+	 * to hardware
+	 */
+	rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+	rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+	rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+	rxq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+	rxq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
+	rxq_cfg.entry_n_pg_size =  ((BNA_RXQ_ENTRY_SIZE >> 2) << 16) |
+	(qpt->page_size >> 2);
+	rxq_cfg.sg_n_cq_n_cns_ptr = (((u8)cfg_ptr->cq_id) << 16) | 0x0;
+	rxq_cfg.buf_sz_n_q_state =
+		(cfg_ptr->buffer_size << 16) | BNA_Q_IDLE_STATE;
+	rxq_cfg.next_qid = 0x0 | (0x3 << 8);
+
+	/* Write the page number register */
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + dev->port,
+		HQM_RXTX_Q_RAM_BASE_OFFSET);
+	bna_reg_write(dev->regs.page_addr, pg_num);
+
+	/* Write to h/w */
+	q_mem = (struct bna_rxtx_q_mem *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0,
+			HQM_RXTX_Q_RAM_BASE_OFFSET);
+		rxq_mem = &q_mem[rxq_id].rxq;
+
+	bna_mem_writew(&rxq_mem->pg_tbl_addr_lo,
+					bna_os_htonl(rxq_cfg.pg_tbl_addr_lo));
+	bna_mem_writew(&rxq_mem->pg_tbl_addr_hi,
+					bna_os_htonl(rxq_cfg.pg_tbl_addr_hi));
+	bna_mem_writew(&rxq_mem->cur_q_entry_lo,
+					bna_os_htonl(rxq_cfg.cur_q_entry_lo));
+	bna_mem_writew(&rxq_mem->cur_q_entry_hi,
+					bna_os_htonl(rxq_cfg.cur_q_entry_hi));
+
+	bna_mem_writew(&rxq_mem->pg_cnt_n_prd_ptr, rxq_cfg.pg_cnt_n_prd_ptr);
+	bna_mem_writew(&rxq_mem->entry_n_pg_size, rxq_cfg.entry_n_pg_size);
+	bna_mem_writew(&rxq_mem->sg_n_cq_n_cns_ptr,
+			rxq_cfg.sg_n_cq_n_cns_ptr);
+	bna_mem_writew(&rxq_mem->buf_sz_n_q_state,
+			rxq_cfg.buf_sz_n_q_state);
+	bna_mem_writew(&rxq_mem->next_qid, rxq_cfg.next_qid);
+
+	DPRINTK(DEBUG, "RxQ %u\n", rxq_id);
+	DPRINTK(DEBUG, "RxQ pg_tbl_addr_lo 0x%x\n",
+		bna_os_ntohl(rxq_cfg.pg_tbl_addr_lo));
+	DPRINTK(DEBUG, "RxQ cur_q_entry_lo 0x%x\n",
+		bna_os_ntohl(rxq_cfg.cur_q_entry_lo));
+	DPRINTK(DEBUG, "RxQ pg_cnt_n_prd_ptr 0x%x\n", rxq_cfg.pg_cnt_n_prd_ptr);
+	DPRINTK(DEBUG, "RxQ entry_n_pg_size 0x%x\n", rxq_cfg.entry_n_pg_size);
+	DPRINTK(DEBUG, "RxQ sg_n_cq_n_cns_ptr 0x%x\n",
+		rxq_cfg.sg_n_cq_n_cns_ptr);
+	DPRINTK(DEBUG, "RxQ buf_sz_n_q_state 0x%x\n", rxq_cfg.buf_sz_n_q_state);
+	DPRINTK(DEBUG, "RxQ next_qid %u\n", rxq_cfg.next_qid);
+
+	qset = (struct bna_doorbell_qset *)
+			BNA_GET_DOORBELL_BASE_ADDR(dev->bar0);
+	q_ptr->doorbell = &qset[rxq_id].rxq[0];
+
+	q_ptr->q.producer_index = 0;
+	q_ptr->q.consumer_index = 0;
+}
+
+
+/**
+ * bna_rxq_stop()
+ *
+ * 	Stops the RxQ identified by the RxQ Id.
+ *	Should be called with a lock held
+ *	The driver should wait for the response to
+ *	conclude if the Q stop is successful or not.
+ *
+ * @param[in] q_id	- Id of the RxQ
+ *
+ * @return    BNA_OK in case of success, else BNA_FAIL
+ */
+enum bna_status_e
+bna_rxq_stop(struct bna_dev_s *dev, u32 rxq_id)
+{
+	struct bfi_ll_q_stop_req ll_req;
+	u64 bit_mask = 1 << rxq_id;
+
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_RXQ_STOP_REQ;
+	ll_req.mh.mtag.i2htok = 0;
+
+	ll_req.q_id_mask[0] = bna_os_htonl((u32)bit_mask);
+	ll_req.q_id_mask[1] = bna_os_htonl((u32)(bit_mask >> 32));
+
+	/* send to f/w */
+	return bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+}
+
+enum bna_status_e
+bna_multi_rxq_stop(struct bna_dev_s *dev, u64 rxq_id_mask)
+{
+	struct bfi_ll_q_stop_req ll_req;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0);
+
+	ll_req.q_id_mask[0] = bna_os_htonl((u32)rxq_id_mask);
+	ll_req.q_id_mask[1] = bna_os_htonl((u32)(rxq_id_mask >> 32));
+
+	/* send to f/w */
+	return bna_mbox_send(dev, &ll_req, sizeof(ll_req), dev->cbarg);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *  bna_cq_config()
+ *
+ *  For CQ "cq_id", it configures the Rx-Completion Queue as specified by
+ *  "cfg_ptr".
+ *-----------------------------------------------------------------------------
+ */
+void
+bna_cq_config(struct bna_dev_s *dev, struct bna_cq *q_ptr,
+     unsigned int cq_id, const struct bna_cq_config *cfg_ptr)
+{
+	struct bna_cq_mem cq_cfg, *cq_mem;
+	const struct bna_qpt *qpt = &cfg_ptr->qpt;
+	struct bna_dma_addr cur_q_addr;
+	u32 pg_num;
+
+	BNA_ASSERT(cq_id < BNA_CQ_ID_MAX);
+
+	/* Check if the depth is a power of 2 */
+	/* How do we ensure this ? */
+	BNA_ASSERT(BNA_POWER_OF_2(q_ptr->q.q_depth));
+
+
+	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+
+	/*
+	 * Fill out structure, to be subsequently written
+	 * to hardware
+	 */
+	cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+	cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+	cq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+	cq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+	cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
+	cq_cfg.entry_n_pg_size = ((BNA_CQ_ENTRY_SIZE >> 2) << 16) |
+	(qpt->page_size >> 2);
+	cq_cfg.int_blk_n_cns_ptr = ((((u8)cfg_ptr->ib_seg_index) << 24) |
+			(((u8)cfg_ptr->ib_id) << 16) | 0x0);
+	cq_cfg.q_state = BNA_Q_IDLE_STATE;
+
+	/* Write the page number register */
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + dev->port,
+			HQM_CQ_RAM_BASE_OFFSET);
+
+	bna_reg_write(dev->regs.page_addr, pg_num);
+	/* H/W write */
+	cq_mem = (struct bna_cq_mem *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, HQM_CQ_RAM_BASE_OFFSET);
+	bna_mem_writew(&cq_mem[cq_id].pg_tbl_addr_lo,
+					bna_os_htonl(cq_cfg.pg_tbl_addr_lo));
+	bna_mem_writew(&cq_mem[cq_id].pg_tbl_addr_hi,
+					bna_os_htonl(cq_cfg.pg_tbl_addr_hi));
+	bna_mem_writew(&cq_mem[cq_id].cur_q_entry_lo,
+					bna_os_htonl(cq_cfg.cur_q_entry_lo));
+	bna_mem_writew(&cq_mem[cq_id].cur_q_entry_hi,
+					bna_os_htonl(cq_cfg.cur_q_entry_hi));
+
+	bna_mem_writew(&cq_mem[cq_id].pg_cnt_n_prd_ptr,
+					cq_cfg.pg_cnt_n_prd_ptr);
+	bna_mem_writew(&cq_mem[cq_id].entry_n_pg_size, cq_cfg.entry_n_pg_size);
+	bna_mem_writew(&cq_mem[cq_id].int_blk_n_cns_ptr,
+					cq_cfg.int_blk_n_cns_ptr);
+	bna_mem_writew(&cq_mem[cq_id].q_state, cq_cfg.q_state);
+
+	DPRINTK(DEBUG, "CQ %u\n", cq_id);
+	DPRINTK(DEBUG, "CQ pg_tbl_addr_lo 0x%x\n",
+		bna_os_ntohl(cq_cfg.pg_tbl_addr_lo));
+	DPRINTK(DEBUG, "CQ cur_q_entry_lo 0x%x\n",
+		bna_os_ntohl(cq_cfg.cur_q_entry_lo));
+	DPRINTK(DEBUG, "CQ pg_cnt_n_prd_ptr 0x%x\n", cq_cfg.pg_cnt_n_prd_ptr);
+	DPRINTK(DEBUG, "CQ entry_n_pg_size 0x%x\n", cq_cfg.entry_n_pg_size);
+	DPRINTK(DEBUG, "CQ int_blk_n_cns_ptr 0x%x\n", cq_cfg.int_blk_n_cns_ptr);
+	DPRINTK(DEBUG, "CQ q_state 0x%x\n", cq_cfg.q_state);
+
+	q_ptr->q.producer_index = 0;
+	q_ptr->q.consumer_index = 0;
+
+}
+
+/*
+ * bna_ib_idx_reset()
+ *
+ *   For the specified IB, it clears the IB index
+ *
+ * @param[in] cfg_ptr - pointer to IB Configuration Structure.
+ *
+ * @return none
+ */
+void
+bna_ib_idx_reset(struct bna_dev_s *dev, const struct bna_ib_config *cfg_ptr)
+{
+	u32 i, pg_num, *ib_idx;
+
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + dev->port,
+		HQM_INDX_TBL_RAM_BASE_OFFSET);
+	bna_reg_write(dev->regs.page_addr, pg_num);
+
+	ib_idx = (u32 *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0, HQM_INDX_TBL_RAM_BASE_OFFSET);
+	ib_idx += cfg_ptr->index_table_offset;
+	for (i = 0; i < cfg_ptr->seg_size; i++)
+		*ib_idx++ = 0;
+}
+
+/*
+ * bna_ib_config_set()
+ *
+ *   For IB "ib_id", it configures the Interrupt Block specified by "cfg_ptr".
+ *
+ * @param[in] ib_ptr  - pointer to IB Data Structure.
+ * @param[in] ib_id   - interrupt-block ID
+ * @param[in] cfg_ptr - pointer to IB Configuration Structure.
+ *
+ * @return BNA_OK or BNA_FAIL
+ */
+void
+bna_ib_config_set(struct bna_dev_s *dev, struct bna_ib *ib_ptr,
+    unsigned int ib_id, const struct bna_ib_config *cfg_ptr)
+{
+	struct bna_ib_blk_mem ib_cfg, *ib_mem;
+	u32 pg_num;
+	struct bna_doorbell_qset *qset;
+
+	BNA_ASSERT(ib_id < BNA_IB_ID_MAX);
+
+
+	ib_cfg.host_addr_lo =
+			(u32)(cfg_ptr->ib_seg_addr.lsb);
+	ib_cfg.host_addr_hi =
+			(u32)(cfg_ptr->ib_seg_addr.msb);
+
+	ib_cfg.clsc_n_ctrl_n_msix = ((cfg_ptr->coalescing_timer << 16) |
+			(cfg_ptr->control_flags << 8) | (cfg_ptr->msix_vector));
+	ib_cfg.ipkt_n_ent_n_idxof = ((cfg_ptr->interpkt_timer & 0xf) << 16) |
+			(cfg_ptr->seg_size << 8) |
+			(cfg_ptr->index_table_offset);
+	ib_cfg.ipkt_cnt_cfg_n_unacked = (cfg_ptr->interpkt_count << 24);
+
+	/* Write the page number register */
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + dev->port,
+			HQM_IB_RAM_BASE_OFFSET);
+	bna_reg_write(dev->regs.page_addr, pg_num);
+
+	ib_mem = (struct bna_ib_blk_mem *)
+		BNA_GET_MEM_BASE_ADDR(dev->bar0,
+			HQM_IB_RAM_BASE_OFFSET);
+
+	bna_mem_writew(&ib_mem[ib_id].host_addr_lo,
+					bna_os_htonl(ib_cfg.host_addr_lo));
+	bna_mem_writew(&ib_mem[ib_id].host_addr_hi,
+					bna_os_htonl(ib_cfg.host_addr_hi));
+
+	bna_mem_writew(&ib_mem[ib_id].clsc_n_ctrl_n_msix,
+			ib_cfg.clsc_n_ctrl_n_msix);
+	bna_mem_writew(&ib_mem[ib_id].ipkt_n_ent_n_idxof,
+			ib_cfg.ipkt_n_ent_n_idxof);
+	bna_mem_writew(&ib_mem[ib_id].ipkt_cnt_cfg_n_unacked,
+			ib_cfg.ipkt_cnt_cfg_n_unacked);
+
+	DPRINTK(DEBUG, "IB %d: host addr 0x%x clsc_n_ctrl_n_msix 0x%x\n",
+		ib_id, bna_os_htonl(ib_cfg.host_addr_lo),
+		ib_cfg.clsc_n_ctrl_n_msix);
+	DPRINTK(DEBUG, "ipkt_n_ent_n_idxof 0x%x ipkt_cnt_cfg_n_unacked 0x%x\n",
+		ib_cfg.ipkt_n_ent_n_idxof, ib_cfg.ipkt_cnt_cfg_n_unacked);
+
+	qset = (struct bna_doorbell_qset *)
+			BNA_GET_DOORBELL_BASE_ADDR(dev->bar0);
+	ib_ptr->doorbell_addr =
+		(&qset[ib_id >> 1].ib0[(ib_id & 0x1) * (0x20 >> 2)]);
+
+	ib_ptr->doorbell_ack  = BNA_DOORBELL_IB_INT_ACK(
+			cfg_ptr->coalescing_timer, 0);
+
+	bna_ib_idx_reset(dev, cfg_ptr);
+}
+
+/*
+ * bna_ib_disable()
+ *
+ *   Disables the Interrupt Block "ib_id".
+ *
+ * @param[in] ib_ptr  - pointer to IB Data Structure.
+ *
+ * @return None
+ */
+void
+bna_ib_disable(struct bna_dev_s *bna_dev, const struct bna_ib *ib_ptr)
+{
+	bna_reg_write(ib_ptr->doorbell_addr, BNA_DOORBELL_IB_INT_DISABLE);
+}
diff -ruP net-next-2.6-orig/drivers/net/bna/bnad_ethtool.c net-next-2.6-mod/drivers/net/bna/bnad_ethtool.c
--- net-next-2.6-orig/drivers/net/bna/bnad_ethtool.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bnad_ethtool.c	2009-10-31 21:34:47.690539000 -0700
@@ -0,0 +1,1094 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ */
+
+/**
+ *  bna_ethtool.c  Brocade 10G PCIe Ethernet driver.
+ */
+
+#include <linux/types.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/rtnetlink.h>
+
+#include "bnad.h"
+#include "bna_os.h"
+#include "bna_hwreg.h"
+#include "bna_iocll.h"
+#include "bnad_defs.h"
+#include "phyport_defs.h"
+
+#define BNAD_ETHTOOL_STATS_NUM						\
+    (sizeof(struct net_device_stats) / sizeof(unsigned long) +	\
+    sizeof(struct bnad_drv_stats) / sizeof(u64) +		\
+     (offsetof(struct bna_stats, rxf_stats[0]) +			\
+    sizeof(struct bna_stats_txf)) / sizeof(u64))
+
+static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
+	"rx_packets",
+	"tx_packets",
+	"rx_bytes",
+	"tx_bytes",
+	"rx_errors",
+	"tx_errors",
+	"rx_dropped",
+	"tx_dropped",
+	"multicast",
+	"collisions",
+
+	"rx_length_errors",
+	"rx_over_errors",
+	"rx_crc_errors",
+	"rx_frame_errors",
+	"rx_fifo_errors",
+	"rx_missed_errors",
+
+	"tx_aborted_errors",
+	"tx_carrier_errors",
+	"tx_fifo_errors",
+	"tx_heartbeat_errors",
+	"tx_window_errors",
+
+	"rx_compressed",
+	"tx_compressed",
+
+	"netif_queue_stop",
+	"netif_queue_wakeup",
+	"tso4",
+	"tso6",
+	"tso_err",
+	"tcpcsum_offload",
+	"udpcsum_offload",
+	"csum_help",
+	"csum_help_err",
+	"hw_stats_updates",
+	"netif_rx_schedule",
+	"netif_rx_complete",
+	"netif_rx_dropped",
+
+	"mac_frame_64",
+	"mac_frame_65_127",
+	"mac_frame_128_255",
+	"mac_frame_256_511",
+	"mac_frame_512_1023",
+	"mac_frame_1024_1518",
+	"mac_frame_1518_1522",
+	"mac_rx_bytes",
+	"mac_rx_packets",
+	"mac_rx_fcs_error",
+	"mac_rx_multicast",
+	"mac_rx_broadcast",
+	"mac_rx_control_frames",
+	"mac_rx_pause",
+	"mac_rx_unknown_opcode",
+	"mac_rx_alignment_error",
+	"mac_rx_frame_length_error",
+	"mac_rx_code_error",
+	"mac_rx_carrier_sense_error",
+	"mac_rx_undersize",
+	"mac_rx_oversize",
+	"mac_rx_fragments",
+	"mac_rx_jabber",
+	"mac_rx_drop",
+
+	"bpc_rx_pause_0",
+	"bpc_rx_pause_1",
+	"bpc_rx_pause_2",
+	"bpc_rx_pause_3",
+	"bpc_rx_pause_4",
+	"bpc_rx_pause_5",
+	"bpc_rx_pause_6",
+	"bpc_rx_pause_7",
+	"bpc_rx_zero_pause_0",
+	"bpc_rx_zero_pause_1",
+	"bpc_rx_zero_pause_2",
+	"bpc_rx_zero_pause_3",
+	"bpc_rx_zero_pause_4",
+	"bpc_rx_zero_pause_5",
+	"bpc_rx_zero_pause_6",
+	"bpc_rx_zero_pause_7",
+	"bpc_rx_first_pause_0",
+	"bpc_rx_first_pause_1",
+	"bpc_rx_first_pause_2",
+	"bpc_rx_first_pause_3",
+	"bpc_rx_first_pause_4",
+	"bpc_rx_first_pause_5",
+	"bpc_rx_first_pause_6",
+	"bpc_rx_first_pause_7",
+
+	"rad_rx_frames",
+	"rad_rx_octets",
+	"rad_rx_vlan_frames",
+	"rad_rx_ucast",
+	"rad_rx_ucast_octets",
+	"rad_rx_ucast_vlan",
+	"rad_rx_mcast",
+	"rad_rx_mcast_octets",
+	"rad_rx_mcast_vlan",
+	"rad_rx_bcast",
+	"rad_rx_bcast_octets",
+	"rad_rx_bcast_vlan",
+	"rad_rx_drops",
+
+	"fc_rx_ucast_octets",
+	"fc_rx_ucast",
+	"fc_rx_ucast_vlan",
+	"fc_rx_mcast_octets",
+	"fc_rx_mcast",
+	"fc_rx_mcast_vlan",
+	"fc_rx_bcast_octets",
+	"fc_rx_bcast",
+	"fc_rx_bcast_vlan",
+
+	"mac_tx_bytes",
+	"mac_tx_packets",
+	"mac_tx_multicast",
+	"mac_tx_broadcast",
+	"mac_tx_pause",
+	"mac_tx_deferral",
+	"mac_tx_excessive_deferral",
+	"mac_tx_single_collision",
+	"mac_tx_muliple_collision",
+	"mac_tx_late_collision",
+	"mac_tx_excessive_collision",
+	"mac_tx_total_collision",
+	"mac_tx_pause_honored",
+	"mac_tx_drop",
+	"mac_tx_jabber",
+	"mac_tx_fcs_error",
+	"mac_tx_control_frame",
+	"mac_tx_oversize",
+	"mac_tx_undersize",
+	"mac_tx_fragments",
+
+	"bpc_tx_pause_0",
+	"bpc_tx_pause_1",
+	"bpc_tx_pause_2",
+	"bpc_tx_pause_3",
+	"bpc_tx_pause_4",
+	"bpc_tx_pause_5",
+	"bpc_tx_pause_6",
+	"bpc_tx_pause_7",
+	"bpc_tx_zero_pause_0",
+	"bpc_tx_zero_pause_1",
+	"bpc_tx_zero_pause_2",
+	"bpc_tx_zero_pause_3",
+	"bpc_tx_zero_pause_4",
+	"bpc_tx_zero_pause_5",
+	"bpc_tx_zero_pause_6",
+	"bpc_tx_zero_pause_7",
+	"bpc_tx_first_pause_0",
+	"bpc_tx_first_pause_1",
+	"bpc_tx_first_pause_2",
+	"bpc_tx_first_pause_3",
+	"bpc_tx_first_pause_4",
+	"bpc_tx_first_pause_5",
+	"bpc_tx_first_pause_6",
+	"bpc_tx_first_pause_7",
+
+	"fc_tx_ucast_octets",
+	"fc_tx_ucast",
+	"fc_tx_ucast_vlan",
+	"fc_tx_mcast_octets",
+	"fc_tx_mcast",
+	"fc_tx_mcast_vlan",
+	"fc_tx_bcast_octets",
+	"fc_tx_bcast",
+	"fc_tx_bcast_vlan",
+	"fc_tx_parity_errors",
+	"fc_tx_timeout",
+	"fc_tx_fid_parity_errors",
+
+	"txf0_ucast_octets",
+	"txf0_ucast",
+	"txf0_ucast_vlan",
+	"txf0_mcast_octets",
+	"txf0_mcast",
+	"txf0_mcast_vlan",
+	"txf0_bcast_octets",
+	"txf0_bcast",
+	"txf0_bcast_vlan",
+	"txf0_errors",
+	"txf0_filter_vlan",
+	"txf0_filter_mac_sa"
+};
+
+static int bnad_get_regs_len(struct net_device *netdev);
+
+static int bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bna_port_param port_param;
+
+	bnad_lock();
+	spin_lock_irq(&bnad->priv_lock);
+	bna_port_param_get(bnad->priv, &port_param);
+	spin_unlock_irq(&bnad->priv_lock);
+
+	if (port_param.speed == BNA_LINK_SPEED_10Gbps) {
+		cmd->supported = SUPPORTED_10000baseT_Full;
+		cmd->advertising = ADVERTISED_10000baseT_Full;
+	}
+
+	/* In future we may support autoneg, currently we don't */
+	if (port_param.autoneg) {
+		cmd->supported |= SUPPORTED_Autoneg;
+		cmd->advertising |= ADVERTISED_Autoneg;
+		cmd->autoneg = AUTONEG_ENABLE;
+	} else
+		cmd->autoneg = AUTONEG_DISABLE;
+	cmd->supported |= SUPPORTED_FIBRE;
+	cmd->advertising |= ADVERTISED_FIBRE;
+	cmd->port = PORT_FIBRE;
+	cmd->phy_address = 0;
+
+	if (netif_carrier_ok(netdev)) {
+		cmd->speed = SPEED_10000;
+		cmd->duplex = DUPLEX_FULL;
+	} else {
+		cmd->speed = -1;
+		cmd->duplex = -1;
+	}
+	cmd->transceiver = XCVR_EXTERNAL;
+	cmd->maxtxpkt = 0;
+	cmd->maxrxpkt = 0;
+	bnad_unlock();
+	return 0;
+}
+
+static int bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	/* 10G full duplex setting supported only */
+	if (cmd->autoneg == AUTONEG_ENABLE) {
+		return -EOPNOTSUPP;
+	} else {
+		if ((cmd->speed == SPEED_10000) && (cmd->duplex == DUPLEX_FULL))
+			return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static void
+bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bfa_ioc_attr_s *ioc_attr;
+
+	strcpy(drvinfo->driver, BNAD_NAME);
+	strcpy(drvinfo->version, BNAD_VERSION);
+
+	ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
+	if (ioc_attr) {
+		memset(ioc_attr, 0, sizeof(*ioc_attr));
+		spin_lock_irq(&bnad->priv_lock);
+		bna_iocll_getattr(bnad->priv, ioc_attr);
+		spin_unlock_irq(&bnad->priv_lock);
+
+		strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
+		    sizeof(drvinfo->fw_version) - 1);
+		kfree(ioc_attr);
+	}
+
+	strncpy(drvinfo->bus_info, pci_name(bnad->pcidev),
+	    ETHTOOL_BUSINFO_LEN);
+}
+
+static int get_regs(struct bnad *bnad, u32 *regs)
+{
+	int num = 0, i;
+	u32 reg_addr;
+
+#define BNAD_GET_REG(addr) 					\
+do {								\
+	if (regs)						\
+		regs[num++] = readl(bnad->bar0 + (addr));      \
+	else							\
+		num++;						\
+} while (0)
+
+	/* DMA Block Internal Registers */
+	BNAD_GET_REG(DMA_CTRL_REG0);
+	BNAD_GET_REG(DMA_CTRL_REG1);
+	BNAD_GET_REG(DMA_ERR_INT_STATUS);
+	BNAD_GET_REG(DMA_ERR_INT_ENABLE);
+	BNAD_GET_REG(DMA_ERR_INT_STATUS_SET);
+
+	/* APP Block Register Address Offset from BAR0 */
+	BNAD_GET_REG(HOSTFN0_INT_STATUS);
+	BNAD_GET_REG(HOSTFN0_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN0);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0);
+	BNAD_GET_REG(FN0_PCIE_ERR_REG);
+	BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG);
+
+	BNAD_GET_REG(HOSTFN1_INT_STATUS);
+	BNAD_GET_REG(HOSTFN1_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN1);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1);
+	BNAD_GET_REG(FN1_PCIE_ERR_REG);
+	BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG);
+
+	BNAD_GET_REG(PCIE_MISC_REG);
+
+	BNAD_GET_REG(HOST_SEM0_REG);
+	BNAD_GET_REG(HOST_SEM1_REG);
+	BNAD_GET_REG(HOST_SEM2_REG);
+	BNAD_GET_REG(HOST_SEM3_REG);
+	BNAD_GET_REG(HOST_SEM0_INFO_REG);
+	BNAD_GET_REG(HOST_SEM1_INFO_REG);
+	BNAD_GET_REG(HOST_SEM2_INFO_REG);
+	BNAD_GET_REG(HOST_SEM3_INFO_REG);
+
+	BNAD_GET_REG(TEMPSENSE_CNTL_REG);
+	BNAD_GET_REG(TEMPSENSE_STAT_REG);
+
+	BNAD_GET_REG(APP_LOCAL_ERR_STAT);
+	BNAD_GET_REG(APP_LOCAL_ERR_MSK);
+
+	BNAD_GET_REG(PCIE_LNK_ERR_STAT);
+	BNAD_GET_REG(PCIE_LNK_ERR_MSK);
+
+	BNAD_GET_REG(FCOE_FIP_ETH_TYPE);
+	BNAD_GET_REG(RESV_ETH_TYPE);
+
+	BNAD_GET_REG(HOSTFN2_INT_STATUS);
+	BNAD_GET_REG(HOSTFN2_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN2);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2);
+	BNAD_GET_REG(FN2_PCIE_ERR_REG);
+	BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG);
+
+	BNAD_GET_REG(HOSTFN3_INT_STATUS);
+	BNAD_GET_REG(HOSTFN3_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN3);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3);
+	BNAD_GET_REG(FN3_PCIE_ERR_REG);
+	BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG);
+
+	/* Host Command Status Registers */
+	reg_addr = HOST_CMDSTS0_CLR_REG;
+	for (i = 0; i < 16; i++) {
+		BNAD_GET_REG(reg_addr);
+		BNAD_GET_REG(reg_addr + 4);
+		BNAD_GET_REG(reg_addr + 8);
+		reg_addr += 0x10;
+	}
+
+	/* Function ID register */
+	BNAD_GET_REG(FNC_ID_REG);
+
+	/* Function personality register */
+	BNAD_GET_REG(FNC_PERS_REG);
+
+	/* Operation mode register */
+	BNAD_GET_REG(OP_MODE);
+
+	/* LPU0 Registers */
+	BNAD_GET_REG(LPU0_MBOX_CTL_REG);
+	BNAD_GET_REG(LPU0_MBOX_CMD_REG);
+	BNAD_GET_REG(LPU0_MBOX_LINK_0REG);
+	BNAD_GET_REG(LPU1_MBOX_LINK_0REG);
+	BNAD_GET_REG(LPU0_MBOX_STATUS_0REG);
+	BNAD_GET_REG(LPU1_MBOX_STATUS_0REG);
+	BNAD_GET_REG(LPU0_ERR_STATUS_REG);
+	BNAD_GET_REG(LPU0_ERR_SET_REG);
+
+	/* LPU1 Registers */
+	BNAD_GET_REG(LPU1_MBOX_CTL_REG);
+	BNAD_GET_REG(LPU1_MBOX_CMD_REG);
+	BNAD_GET_REG(LPU0_MBOX_LINK_1REG);
+	BNAD_GET_REG(LPU1_MBOX_LINK_1REG);
+	BNAD_GET_REG(LPU0_MBOX_STATUS_1REG);
+	BNAD_GET_REG(LPU1_MBOX_STATUS_1REG);
+	BNAD_GET_REG(LPU1_ERR_STATUS_REG);
+	BNAD_GET_REG(LPU1_ERR_SET_REG);
+
+	/* PSS Registers */
+	BNAD_GET_REG(PSS_CTL_REG);
+	BNAD_GET_REG(PSS_ERR_STATUS_REG);
+	BNAD_GET_REG(ERR_STATUS_SET);
+	BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG);
+
+	/* Catapult CPQ Registers */
+	BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT);
+
+	/* Host Function Force Parity Error Registers */
+	BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR);
+	BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR);
+	BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR);
+	BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR);
+
+	/* LL Port[0|1] Halt Mask Registers */
+	BNAD_GET_REG(LL_HALT_MSK_P0);
+	BNAD_GET_REG(LL_HALT_MSK_P1);
+
+	/* LL Port[0|1] Error Mask Registers */
+	BNAD_GET_REG(LL_ERR_MSK_P0);
+	BNAD_GET_REG(LL_ERR_MSK_P1);
+
+	/* EMC FLI Registers */
+	BNAD_GET_REG(FLI_CMD_REG);
+	BNAD_GET_REG(FLI_ADDR_REG);
+	BNAD_GET_REG(FLI_CTL_REG);
+	BNAD_GET_REG(FLI_WRDATA_REG);
+	BNAD_GET_REG(FLI_RDDATA_REG);
+	BNAD_GET_REG(FLI_DEV_STATUS_REG);
+	BNAD_GET_REG(FLI_SIG_WD_REG);
+
+	BNAD_GET_REG(FLI_DEV_VENDOR_REG);
+	BNAD_GET_REG(FLI_ERR_STATUS_REG);
+
+	/* RxAdm 0 Registers */
+	BNAD_GET_REG(RAD0_CTL_REG);
+	BNAD_GET_REG(RAD0_PE_PARM_REG);
+	BNAD_GET_REG(RAD0_BCN_REG);
+	BNAD_GET_REG(RAD0_DEFAULT_REG);
+	BNAD_GET_REG(RAD0_PROMISC_REG);
+	BNAD_GET_REG(RAD0_BCNQ_REG);
+	BNAD_GET_REG(RAD0_DEFAULTQ_REG);
+
+	BNAD_GET_REG(RAD0_ERR_STS);
+	BNAD_GET_REG(RAD0_SET_ERR_STS);
+	BNAD_GET_REG(RAD0_ERR_INT_EN);
+	BNAD_GET_REG(RAD0_FIRST_ERR);
+	BNAD_GET_REG(RAD0_FORCE_ERR);
+
+	BNAD_GET_REG(RAD0_MAC_MAN_1H);
+	BNAD_GET_REG(RAD0_MAC_MAN_1L);
+	BNAD_GET_REG(RAD0_MAC_MAN_2H);
+	BNAD_GET_REG(RAD0_MAC_MAN_2L);
+	BNAD_GET_REG(RAD0_MAC_MAN_3H);
+	BNAD_GET_REG(RAD0_MAC_MAN_3L);
+	BNAD_GET_REG(RAD0_MAC_MAN_4H);
+	BNAD_GET_REG(RAD0_MAC_MAN_4L);
+
+	BNAD_GET_REG(RAD0_LAST4_IP);
+
+	/* RxAdm 1 Registers */
+	BNAD_GET_REG(RAD1_CTL_REG);
+	BNAD_GET_REG(RAD1_PE_PARM_REG);
+	BNAD_GET_REG(RAD1_BCN_REG);
+	BNAD_GET_REG(RAD1_DEFAULT_REG);
+	BNAD_GET_REG(RAD1_PROMISC_REG);
+	BNAD_GET_REG(RAD1_BCNQ_REG);
+	BNAD_GET_REG(RAD1_DEFAULTQ_REG);
+
+	BNAD_GET_REG(RAD1_ERR_STS);
+	BNAD_GET_REG(RAD1_SET_ERR_STS);
+	BNAD_GET_REG(RAD1_ERR_INT_EN);
+
+	/* TxA0 Registers */
+	BNAD_GET_REG(TXA0_CTRL_REG);
+	/* TxA0 TSO Sequence # Registers (RO) */
+	for (i = 0; i < 8; i++) {
+		BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i));
+		BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i));
+	}
+
+	/* TxA1 Registers */
+	BNAD_GET_REG(TXA1_CTRL_REG);
+	/* TxA1 TSO Sequence # Registers (RO) */
+	for (i = 0; i < 8; i++) {
+		BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i));
+		BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i));
+	}
+
+	/* RxA Registers */
+	BNAD_GET_REG(RXA0_CTL_REG);
+	BNAD_GET_REG(RXA1_CTL_REG);
+
+	/* PLB0 Registers */
+	BNAD_GET_REG(PLB0_ECM_TIMER_REG);
+	BNAD_GET_REG(PLB0_RL_CTL);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB0_RL_MAX_BC(i));
+	BNAD_GET_REG(PLB0_RL_TU_PRIO);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB0_RL_BYTE_CNT(i));
+	BNAD_GET_REG(PLB0_RL_MIN_REG);
+	BNAD_GET_REG(PLB0_RL_MAX_REG);
+	BNAD_GET_REG(PLB0_EMS_ADD_REG);
+
+	/* PLB1 Registers */
+	BNAD_GET_REG(PLB1_ECM_TIMER_REG);
+	BNAD_GET_REG(PLB1_RL_CTL);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB1_RL_MAX_BC(i));
+	BNAD_GET_REG(PLB1_RL_TU_PRIO);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB1_RL_BYTE_CNT(i));
+	BNAD_GET_REG(PLB1_RL_MIN_REG);
+	BNAD_GET_REG(PLB1_RL_MAX_REG);
+	BNAD_GET_REG(PLB1_EMS_ADD_REG);
+
+	/* HQM Control Register */
+	BNAD_GET_REG(HQM0_CTL_REG);
+	BNAD_GET_REG(HQM0_RXQ_STOP_SEM);
+	BNAD_GET_REG(HQM0_TXQ_STOP_SEM);
+	BNAD_GET_REG(HQM1_CTL_REG);
+	BNAD_GET_REG(HQM1_RXQ_STOP_SEM);
+	BNAD_GET_REG(HQM1_TXQ_STOP_SEM);
+
+	/* LUT Registers */
+	BNAD_GET_REG(LUT0_ERR_STS);
+	BNAD_GET_REG(LUT0_SET_ERR_STS);
+	BNAD_GET_REG(LUT1_ERR_STS);
+	BNAD_GET_REG(LUT1_SET_ERR_STS);      \
+
+	/* TRC Registers */
+	BNAD_GET_REG(TRC_CTL_REG);
+	BNAD_GET_REG(TRC_MODS_REG);
+	BNAD_GET_REG(TRC_TRGC_REG);
+	BNAD_GET_REG(TRC_CNT1_REG);
+	BNAD_GET_REG(TRC_CNT2_REG);
+	BNAD_GET_REG(TRC_NXTS_REG);
+	BNAD_GET_REG(TRC_DIRR_REG);
+	for (i = 0; i < 10; i++)
+		BNAD_GET_REG(TRC_TRGM_REG(i));
+	for (i = 0; i < 10; i++)
+		BNAD_GET_REG(TRC_NXTM_REG(i));
+	for (i = 0; i < 10; i++)
+		BNAD_GET_REG(TRC_STRM_REG(i));
+
+#undef BNAD_GET_REG
+	return num;
+}
+
+static int bnad_get_regs_len(struct net_device *netdev)
+{
+	return get_regs(netdev_priv(netdev), NULL) * sizeof(u32);
+}
+
+static void
+bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
+{
+	memset(buf, 0, bnad_get_regs_len(netdev));
+	get_regs(netdev_priv(netdev), buf);
+}
+
+static void
+bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)
+{
+	wolinfo->supported = 0;
+	wolinfo->wolopts = 0;
+}
+
+
+static int
+bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	bnad_lock();
+	coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo *
+	    BNAD_COALESCING_TIMER_UNIT;
+	coalesce->rx_max_coalesced_frames = bnad->rx_interpkt_count;
+	coalesce->rx_coalesce_usecs_irq = bnad->rx_interpkt_timeo;
+	coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo *
+	    BNAD_COALESCING_TIMER_UNIT;
+	coalesce->tx_max_coalesced_frames = bnad->tx_interpkt_count;
+
+	coalesce->use_adaptive_rx_coalesce = bnad->rx_dyn_coalesce_on;
+	bnad_unlock();
+	return 0;
+}
+
+static int
+bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int i, err = 0, reset = 0;
+	u16 ib_id;
+
+	if (coalesce->rx_coalesce_usecs == 0 || coalesce->rx_coalesce_usecs >
+	    BNAD_MAX_COALESCING_TIMEO * BNAD_COALESCING_TIMER_UNIT)
+		return -EINVAL;
+	if (coalesce->rx_max_coalesced_frames > BNAD_MAX_INTERPKT_COUNT)
+		return -EINVAL;
+	if (coalesce->rx_coalesce_usecs_irq == 0 ||
+	    coalesce->rx_coalesce_usecs_irq > BNAD_MAX_INTERPKT_TIMEO)
+		return -EINVAL;
+
+	if (coalesce->tx_coalesce_usecs == 0 || coalesce->tx_coalesce_usecs >
+	    BNAD_MAX_COALESCING_TIMEO * BNAD_COALESCING_TIMER_UNIT)
+		return -EINVAL;
+	if (coalesce->tx_max_coalesced_frames > BNAD_MAX_INTERPKT_COUNT)
+		return -EINVAL;
+
+	bnad_lock();
+
+	bnad->rx_dyn_coalesce_on = coalesce->use_adaptive_rx_coalesce;
+
+	bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs /
+	    BNAD_COALESCING_TIMER_UNIT;
+	if (bnad->rx_coalescing_timeo == 0)
+		bnad->rx_coalescing_timeo = 1;
+	if (!test_bit(BNAD_DISABLED, &bnad->state)) {
+		for (i = 0; i < bnad->cq_num; i++) {
+			ib_id = bnad->cq_table[i].cq_config.ib_id;
+			bnad->ib_table[ib_id].ib_config.coalescing_timer =
+			    bnad->rx_coalescing_timeo;
+			if (!bnad->rx_dyn_coalesce_on) {
+				bnad->cq_table[i].rx_coalescing_timeo =
+					bnad->rx_coalescing_timeo;
+			}
+		}
+	}
+	if (coalesce->rx_max_coalesced_frames != bnad->rx_interpkt_count) {
+		bnad->rx_interpkt_count = coalesce->rx_max_coalesced_frames;
+		reset++;
+	}
+	if (coalesce->rx_coalesce_usecs_irq != bnad->rx_interpkt_timeo) {
+		bnad->rx_interpkt_timeo = coalesce->rx_coalesce_usecs_irq;
+		reset++;
+	}
+
+	bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs /
+	    BNAD_COALESCING_TIMER_UNIT;
+	if (bnad->tx_coalescing_timeo == 0)
+		bnad->tx_coalescing_timeo = 1;
+	if (!test_bit(BNAD_DISABLED, &bnad->state)) {
+		for (i = 0; i < bnad->txq_num; i++) {
+			ib_id = bnad->txq_table[i].txq_config.ib_id;
+			bnad->ib_table[ib_id].ib_config.coalescing_timer =
+			    bnad->tx_coalescing_timeo;
+		}
+	}
+	if (coalesce->tx_max_coalesced_frames != bnad->tx_interpkt_count) {
+		bnad->tx_interpkt_count = coalesce->tx_max_coalesced_frames;
+		reset++;
+	}
+
+	if (reset)
+		err = bnad_sw_reset(netdev);
+
+	bnad_unlock();
+
+	return err;
+}
+
+static void bnad_get_ringparam(struct net_device *netdev,
+    struct ethtool_ringparam *ringparam)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	bnad_lock();
+	ringparam->rx_max_pending = BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq;
+	ringparam->rx_mini_max_pending = 0;
+	ringparam->rx_jumbo_max_pending = 0;
+	ringparam->tx_max_pending = BNAD_MAX_Q_DEPTH;
+
+	ringparam->rx_pending = bnad->rxq_depth;
+	ringparam->rx_mini_max_pending = 0;
+	ringparam->rx_jumbo_max_pending = 0;
+	ringparam->tx_pending = bnad->txq_depth;
+	bnad_unlock();
+}
+
+static int bnad_set_ringparam(struct net_device *netdev,
+    struct ethtool_ringparam *ringparam)
+{
+	int err = 0;
+	struct bnad *bnad = netdev_priv(netdev);
+	bnad_lock();
+	if (ringparam->rx_pending == bnad->rxq_depth &&
+	    ringparam->tx_pending == bnad->txq_depth) {
+		bnad_unlock();
+		return 0;
+	}
+
+	if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH ||
+	    ringparam->rx_pending > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq ||
+	    !BNA_POWER_OF_2(ringparam->rx_pending)) {
+		bnad_unlock();
+		return -EINVAL;
+	}
+	if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH ||
+	    ringparam->tx_pending > BNAD_MAX_Q_DEPTH ||
+	    !BNA_POWER_OF_2(ringparam->tx_pending)) {
+		bnad_unlock();
+		return -EINVAL;
+	}
+
+	if (ringparam->rx_pending != bnad->rxq_depth) {
+		bnad->rxq_depth = ringparam->rx_pending;
+		bnad->flags |= BNAD_F_RXQ_DEPTH;
+	}
+	if (ringparam->tx_pending != bnad->txq_depth) {
+		bnad->txq_depth = ringparam->tx_pending;
+		bnad->flags |= BNAD_F_TXQ_DEPTH;
+	}
+
+	err =  bnad_sw_reset(netdev);
+	bnad_unlock();
+	return err;
+}
+
+static void bnad_get_pauseparam(struct net_device *netdev,
+    struct ethtool_pauseparam *pauseparam)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	bnad_lock();
+	pauseparam->autoneg = 0;
+	pauseparam->rx_pause = bnad->pause_config.rx_pause;
+	pauseparam->tx_pause = bnad->pause_config.tx_pause;
+	bnad_unlock();
+}
+
+static int bnad_set_pauseparam(struct net_device *netdev,
+    struct ethtool_pauseparam *pauseparam)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int err;
+
+	if (pauseparam->autoneg == AUTONEG_ENABLE)
+		return -EINVAL;
+	bnad_lock();
+	if (pauseparam->rx_pause != bnad->pause_config.rx_pause ||
+	    pauseparam->tx_pause != bnad->pause_config.tx_pause) {
+		bnad->pause_config.rx_pause = pauseparam->rx_pause;
+		bnad->pause_config.tx_pause = pauseparam->tx_pause;
+		spin_lock_irq(&bnad->priv_lock);
+		err = bna_set_pause_config(bnad->priv,
+			&bnad->pause_config, bnad);
+		BNA_ASSERT(!err);
+		spin_unlock_irq(&bnad->priv_lock);
+	}
+	bnad_unlock();
+	return 0;
+}
+
+static u32 bnad_get_rx_csum(struct net_device *netdev)
+{
+	u32 rx_csum;
+	struct bnad *bnad = netdev_priv(netdev);
+
+	bnad_lock();
+	rx_csum = bnad->rx_csum;
+	bnad_unlock();
+	return rx_csum;
+}
+
+static int bnad_set_rx_csum(struct net_device *netdev, u32 rx_csum)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	bnad_lock();
+	bnad->rx_csum = rx_csum;
+	bnad_unlock();
+	return 0;
+}
+
+static int bnad_set_tx_csum(struct net_device *netdev, u32 tx_csum)
+{
+	if (tx_csum) {
+		netdev->features |= NETIF_F_IP_CSUM;
+#ifdef NETIF_F_IPV6_CSUM
+		netdev->features |= NETIF_F_IPV6_CSUM;
+#endif
+	} else {
+		netdev->features &= ~NETIF_F_IP_CSUM;
+#ifdef NETIF_F_IPV6_CSUM
+		netdev->features &= ~NETIF_F_IPV6_CSUM;
+#endif
+	}
+	return 0;
+}
+
+static int bnad_set_tso(struct net_device *netdev, u32 tso)
+{
+	if (tso) {
+		netdev->features |= NETIF_F_TSO;
+		netdev->features |= NETIF_F_TSO6;
+	} else {
+		netdev->features &= ~NETIF_F_TSO;
+		netdev->features &= ~NETIF_F_TSO6;
+	}
+	return 0;
+}
+
+
+static void bnad_get_strings(struct net_device *netdev, u32 stringset,
+							 u8 *string)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int i;
+	bnad_lock();
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {
+			BNA_ASSERT(strlen(bnad_net_stats_strings[i]) <
+				ETH_GSTRING_LEN);
+			memcpy(string, bnad_net_stats_strings[i],
+				ETH_GSTRING_LEN);
+			string += ETH_GSTRING_LEN;
+		}
+
+			i = 0;
+			sprintf(string, "rxf%d_ucast_octets", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_ucast", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_ucast_vlan", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_mcast_octets", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_mcast", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_mcast_vlan", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_bcast_octets", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_bcast", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_bcast_vlan", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxf%d_frame_drops", i);
+			string += ETH_GSTRING_LEN;
+
+		sprintf(string, "netif_queue_stopped");
+		string += ETH_GSTRING_LEN;
+		sprintf(string, "bna_state");
+		string += ETH_GSTRING_LEN;
+
+		for (i = 0; i < bnad->cq_num; i++) {
+			sprintf(string, "cq%d_producer_index", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "cq%d_consumer_index", i);
+			string += ETH_GSTRING_LEN;
+		}
+
+		for (i = 0; i < bnad->rxq_num; i++) {
+			sprintf(string, "rxq%d_packets", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxq%d_bytes", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxq%d_packets_with_error", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxq%d_allocbuf_failed", i);
+			string += ETH_GSTRING_LEN;
+
+			sprintf(string, "rxq%d_producer_index", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "rxq%d_consumer_index", i);
+			string += ETH_GSTRING_LEN;
+
+		}
+
+		for (i = 0; i < bnad->txq_num; i++) {
+			sprintf(string, "txq%d_packets", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "txq%d_bytes", i);
+			string += ETH_GSTRING_LEN;
+
+			sprintf(string, "txq%d_producer_index", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "txq%d_consumer_index", i);
+			string += ETH_GSTRING_LEN;
+			sprintf(string, "txq%d_hw_consumer_index", i);
+			string += ETH_GSTRING_LEN;
+		}
+		break;
+
+	default:
+		break;
+	}
+	bnad_unlock();
+}
+
+
+static void bnad_get_ethtool_stats(struct net_device *netdev,
+	struct ethtool_stats *stats, u64 *buf)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int i, bi, j;
+	unsigned long *net_stats;
+	u64 *stats64;
+
+	bi = 0;
+	bnad_get_stats(netdev);
+
+	net_stats = (unsigned long *)&bnad->net_stats;
+	for (i = 0; i < sizeof(struct net_device_stats) /
+	    sizeof(unsigned long); i++)
+		buf[bi++] = net_stats[i];
+
+	stats64 = (u64 *)&bnad->stats;
+	for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64);
+	    i++)
+		buf[bi++] = stats64[i];
+
+	stats64 = (u64 *)bnad->hw_stats;
+	for (i = 0; i < offsetof(struct bna_stats, rxf_stats[0]) /
+	    sizeof(u64); i++)
+		buf[bi++] = stats64[i];
+
+	stats64 = (u64 *)&bnad->hw_stats->txf_stats[0];
+	for (i = 0; i < sizeof(struct bna_stats_txf) / sizeof(u64); i++)
+		buf[bi++] = stats64[i];
+
+		j = 0;
+		stats64 = (u64 *)&bnad->hw_stats->rxf_stats[j];
+		for (i = 0; i < sizeof(struct bna_stats_rxf) /
+		      sizeof(u64); i++)
+			buf[bi++] = stats64[i];
+
+	buf[bi++] = netif_queue_stopped(netdev);
+	buf[bi++] = bnad->state;
+
+	if (bnad->cq_table && bnad->rxq_table && bnad->txq_table) {
+		for (i = 0; i < bnad->cq_num; i++) {
+			buf[bi++] = bnad->cq_table[i].cq.q.producer_index;
+			buf[bi++] = bnad->cq_table[i].cq.q.consumer_index;
+		}
+
+		for (i = 0; i < bnad->rxq_num; i++) {
+			buf[bi++] = bnad->rxq_table[i].rx_packets;
+			buf[bi++] = bnad->rxq_table[i].rx_bytes;
+			buf[bi++] = bnad->rxq_table[i].rx_packets_with_error;
+			buf[bi++] = bnad->rxq_table[i].rxbuf_alloc_failed;
+
+			buf[bi++] = bnad->rxq_table[i].rxq.q.producer_index;
+			buf[bi++] = bnad->rxq_table[i].rxq.q.consumer_index;
+		}
+		for (i = 0; i < bnad->txq_num; i++) {
+			buf[bi++] = bnad->txq_table[i].tx_packets;
+			buf[bi++] = bnad->txq_table[i].tx_bytes;
+
+			buf[bi++] = bnad->txq_table[i].txq.q.producer_index;
+			buf[bi++] = bnad->txq_table[i].txq.q.consumer_index;
+			buf[bi++] = *(bnad->txq_table[i].hw_consumer_index);
+		}
+	}
+}
+
+
+
+static int
+bnad_get_sset_count(struct net_device *netdev, int stringset)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int count;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		bnad_lock();
+		count = BNAD_ETHTOOL_STATS_NUM + 10 + bnad->rxq_num * 4
+			+ bnad->txq_num * 2;
+		count += 2;
+
+		/* CQ producer_index, consumer_index */
+		count += bnad->cq_num * 2;
+
+		/* RxQ producer_index, consumer_index */
+		count += bnad->rxq_num * 2;
+
+		/* TxQ producer_index, consumer_index, hw_consumer_index */
+		count += bnad->txq_num * 3;
+		bnad_unlock();
+		return count;
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct ethtool_ops bnad_ethtool_ops = {
+	.get_settings           = bnad_get_settings,
+	.set_settings           = bnad_set_settings,
+	.get_drvinfo            = bnad_get_drvinfo,
+	.get_regs_len           = bnad_get_regs_len,
+	.get_regs               = bnad_get_regs,
+	.get_wol                = bnad_get_wol,
+	.get_msglevel		= bnad_get_msglevel,
+	.set_msglevel		= bnad_set_msglevel,
+	.get_link               = ethtool_op_get_link,
+	.get_coalesce           = bnad_get_coalesce,
+	.set_coalesce           = bnad_set_coalesce,
+	.get_ringparam          = bnad_get_ringparam,
+	.set_ringparam          = bnad_set_ringparam,
+	.get_pauseparam         = bnad_get_pauseparam,
+	.set_pauseparam         = bnad_set_pauseparam,
+	.get_rx_csum            = bnad_get_rx_csum,
+	.set_rx_csum            = bnad_set_rx_csum,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum            = bnad_set_tx_csum,
+	.get_sg                 = ethtool_op_get_sg,
+	.set_sg                 = ethtool_op_set_sg,
+	.get_tso                = ethtool_op_get_tso,
+	.set_tso                = bnad_set_tso,
+	.get_flags              = ethtool_op_get_flags,
+	.set_flags              = ethtool_op_set_flags,
+	.get_strings            = bnad_get_strings,
+	.get_ethtool_stats      = bnad_get_ethtool_stats,
+	.get_sset_count		= bnad_get_sset_count
+};
+
+void bnad_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
+}
+

^ permalink raw reply

* Subject: [PATCH 1/6] bna: Brocade 10Gb Ethernet device driver
From: Rasesh Mody @ 2009-11-01  5:03 UTC (permalink / raw)
  To: netdev; +Cc: adapter_linux_open_src_team

From: Rasesh Mody <rmody@brocade.com>

This is patch 1/6 which contains linux driver source for
Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
Re-based source against net-next-2.6 and re-submitting the
patch with few fixes.

We wish this patch to be considered for inclusion in net-next-2.6

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 bnad.c | 3515 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bnad.h |  370 ++++++
 2 files changed, 3885 insertions(+)

diff -ruP net-next-2.6-orig/drivers/net/bna/bnad.c net-next-2.6-mod/drivers/net/bna/bnad.c
--- net-next-2.6-orig/drivers/net/bna/bnad.c	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bnad.c	2009-10-31 21:34:47.559538000 -0700
@@ -0,0 +1,3515 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ */
+
+/**
+ *  bnad.c  Brocade 10G PCIe Ethernet driver.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/delay.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_ether.h>
+#include <linux/workqueue.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/pm.h>
+#include <linux/random.h>
+
+#include <net/checksum.h>
+
+#include "bnad.h"
+#include "bna_os.h"
+#include "bna_iocll.h"
+#include "bna_intr.h"
+#include "bnad_defs.h"
+
+#ifdef BNAD_NO_IP_ALIGN
+#define BNAD_NET_IP_ALIGN 0
+#else
+#define BNAD_NET_IP_ALIGN NET_IP_ALIGN
+#endif
+
+
+
+#define BNAD_TXQ_WI_NEEDED(_vectors)	(((_vectors) + 3) >> 2)
+
+
+static uint bnad_msix = 1;
+module_param(bnad_msix, uint, 0444);
+MODULE_PARM_DESC(bnad_msix, "Enable MSI-X");
+
+uint bnad_small_large_rxbufs = 1;
+module_param(bnad_small_large_rxbufs, uint, 0444);
+MODULE_PARM_DESC(bnad_small_large_rxbufs, "Enable small/large buffer receive");
+
+static uint bnad_rxqsets_used;
+module_param(bnad_rxqsets_used, uint, 0444);
+MODULE_PARM_DESC(bnad_rxqsets_used, "Number of RxQ sets to be used");
+
+static uint bnad_ipid_mode;
+module_param(bnad_ipid_mode, uint, 0444);
+MODULE_PARM_DESC(bnad_ipid_mode, "0 - Use IP ID 0x0000 - 0x7FFF for LSO; "
+    "1 - Use full range of IP ID for LSO");
+
+uint bnad_txq_depth = BNAD_ENTRIES_PER_TXQ;
+module_param(bnad_txq_depth, uint, 0444);
+MODULE_PARM_DESC(bnad_txq_depth, "Maximum number of entries per TxQ");
+
+uint bnad_rxq_depth = BNAD_ENTRIES_PER_RXQ;
+module_param(bnad_rxq_depth, uint, 0444);
+MODULE_PARM_DESC(bnad_rxq_depth, "Maximum number of entries per RxQ");
+
+static uint bnad_vlan_strip = 1;
+module_param(bnad_vlan_strip, uint, 0444);
+MODULE_PARM_DESC(bnad_vlan_strip, "Let the hardware strip off VLAN header");
+
+static uint bnad_log_level = LOG_WARN_LEVEL;
+module_param(bnad_log_level, uint, 0644);
+MODULE_PARM_DESC(bnad_log_level, "Log level");
+
+static uint bnad_ioc_auto_recover = 1;
+module_param(bnad_ioc_auto_recover, uint, 0644);
+MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable auto recovery");
+
+uint bnad_rxqs_per_cq;
+
+static void bnad_disable_msix(struct bnad *bnad);
+static void bnad_free_ibs(struct bnad *bnad);
+static void bnad_set_rx_mode(struct net_device *netdev);
+static void bnad_set_rx_mode_locked(struct net_device *netdev);
+static void bnad_reconfig_vlans(struct bnad *bnad);
+static void bnad_q_num_init(struct bnad *bnad, uint rxqsets);
+static int bnad_set_mac_address(struct net_device *netdev, void *addr);
+static int bnad_set_mac_address_locked(struct net_device *netdev, void *addr);
+static int bnad_change_mtu(struct net_device *netdev, int new_mtu);
+static int bnad_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+static void
+bnad_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+static void bnad_vlan_rx_add_vid(struct net_device *netdev, unsigned short vid);
+static void
+bnad_vlan_rx_kill_vid(struct net_device *netdev, unsigned short vid);
+static void bnad_netpoll(struct net_device *netdev);
+
+static const struct net_device_ops bnad_netdev_ops = {
+	.ndo_open			= bnad_open,
+	.ndo_stop			= bnad_stop,
+	.ndo_start_xmit			= bnad_start_xmit,
+	.ndo_get_stats			= bnad_get_stats,
+	.ndo_set_rx_mode		= &bnad_set_rx_mode,
+	.ndo_set_multicast_list		= bnad_set_rx_mode,
+	.ndo_set_mac_address		= bnad_set_mac_address,
+	.ndo_change_mtu			= bnad_change_mtu,
+	.ndo_do_ioctl			= bnad_ioctl,
+
+	.ndo_vlan_rx_register		= bnad_vlan_rx_register,
+	.ndo_vlan_rx_add_vid		= bnad_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid		= bnad_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller		= bnad_netpoll,
+#endif
+};
+static int bnad_check_module_params(void)
+{
+	/* bnad_msix */
+	if (bnad_msix && bnad_msix != 1)
+		printk(KERN_WARNING "bna: bnad_msix should be 0 or 1, "
+		    "%u is invalid, set bnad_msix to 1\n", bnad_msix);
+
+	/* bnad_small_large_rxbufs */
+	if (bnad_small_large_rxbufs && bnad_small_large_rxbufs != 1)
+		printk(KERN_WARNING "bna: bnad_small_large_rxbufs should be "
+		    "0 or 1, %u is invalid, set bnad_small_large_rxbufs to 1\n",
+		    bnad_small_large_rxbufs);
+	if (bnad_small_large_rxbufs)
+		bnad_rxqs_per_cq = 2;
+	else
+		bnad_rxqs_per_cq = 1;
+
+	/* bnad_rxqsets_used */
+	if (bnad_rxqsets_used > BNAD_MAX_RXQS / bnad_rxqs_per_cq) {
+		printk(KERN_ERR "bna: the maximum value for bnad_rxqsets_used "
+		    "is %u, %u is invalid\n",
+		    BNAD_MAX_RXQS / bnad_rxqs_per_cq, bnad_rxqsets_used);
+		return -EINVAL;
+	}
+	if (!BNA_POWER_OF_2(bnad_rxqsets_used)) {
+		printk(KERN_ERR "bna: bnad_rxqsets_used should be power of 2, "
+		    "%u is invalid\n", bnad_rxqsets_used);
+		return -EINVAL;
+	}
+	if (bnad_rxqsets_used > (uint)num_online_cpus())
+		printk(KERN_WARNING "bna: set bnad_rxqsets_used (%u) "
+		    "larger than number of CPUs (%d) may not be helpful\n",
+		    bnad_rxqsets_used, num_online_cpus());
+
+	/* bnad_ipid_mode */
+	if (bnad_ipid_mode && bnad_ipid_mode != 1) {
+		printk(KERN_ERR "bna: bnad_ipid_mode should be 0 or 1, "
+		    "%u is invalid\n", bnad_ipid_mode);
+		return -EINVAL;
+	}
+
+	/* bnad_txq_depth */
+	if (bnad_txq_depth > BNAD_MAX_Q_DEPTH) {
+		printk(KERN_ERR "bna: bnad_txq_depth should be <= %u, "
+		    "%u is invalid\n", BNAD_MAX_Q_DEPTH, bnad_txq_depth);
+		return -EINVAL;
+	}
+	if (!BNA_POWER_OF_2(bnad_txq_depth)) {
+		printk(KERN_ERR "bna: bnad_txq_depth should be power of 2, "
+		    "%u is invalid\n", bnad_txq_depth);
+		return -EINVAL;
+	}
+	if (bnad_txq_depth < BNAD_MIN_Q_DEPTH) {
+		printk(KERN_ERR "bna: bnad_txq_depth should be >= %u, "
+		    "%u is invalid\n", BNAD_MIN_Q_DEPTH, bnad_txq_depth);
+		return -EINVAL;
+	}
+
+	/* bnad_rxq_depth */
+	if (bnad_rxq_depth > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq) {
+		printk(KERN_ERR "bna: bnad_rxq_depth should be <= %u, "
+		    "%u is invalid\n", BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq,
+		    bnad_rxq_depth);
+		return -EINVAL;
+	}
+	if (!BNA_POWER_OF_2(bnad_rxq_depth)) {
+		printk(KERN_ERR "bna: bnad_rxq_depth should be power of 2, "
+		    "%u is invalid\n", bnad_rxq_depth);
+		return -EINVAL;
+	}
+	if (bnad_rxq_depth < BNAD_MIN_Q_DEPTH) {
+		printk(KERN_ERR "bna: bnad_rxq_depth should be >= %u, "
+		    "%u is invalid\n", BNAD_MIN_Q_DEPTH, bnad_rxq_depth);
+		return -EINVAL;
+	}
+
+	/* bnad_vlan_strip */
+	if (bnad_vlan_strip && bnad_vlan_strip != 1)
+		printk(KERN_WARNING "bna: bnad_vlan_strip should be 0 or 1, "
+		    "%u is invalid, set bnad_vlan_strip to 1\n",
+		    bnad_vlan_strip);
+
+	/* bnad_ioc_auto_recover */
+	if (bnad_ioc_auto_recover && bnad_ioc_auto_recover != 1)
+		printk(KERN_WARNING
+			"bna: bnad_ioc_auto_recover should be 0 or 1, "
+		    "%u is invalid, set bnad_ioc_auto_recover to 1\n",
+		    bnad_ioc_auto_recover);
+
+
+	return 0;
+}
+
+u32 bnad_get_msglevel(struct net_device *netdev)
+{
+	return bnad_log_level;
+}
+
+void bnad_set_msglevel(struct net_device *netdev, u32 msglevel)
+{
+	bnad_log_level = msglevel;
+}
+
+static unsigned int bnad_free_txbufs(struct bnad_txq_info *txqinfo,
+    u16 updated_txq_cons)
+{
+	struct bnad *bnad = txqinfo->bnad;
+	unsigned int sent_packets = 0, sent_bytes = 0;
+	u16 wis, unmap_cons;
+	struct bnad_skb_unmap *unmap_array;
+	struct sk_buff *skb;
+	int i;
+
+	wis = BNAD_Q_INDEX_CHANGE(txqinfo->txq.q.consumer_index,
+	    updated_txq_cons, txqinfo->txq.q.q_depth);
+	BNA_ASSERT(wis <=
+	    BNA_QE_IN_USE_CNT(&txqinfo->txq.q, txqinfo->txq.q.q_depth));
+	unmap_array = txqinfo->skb_unmap_q.unmap_array;
+	unmap_cons = txqinfo->skb_unmap_q.consumer_index;
+	prefetch(&unmap_array[unmap_cons + 1]);
+	while (wis) {
+		skb = unmap_array[unmap_cons].skb;
+		BNA_ASSERT(skb);
+		unmap_array[unmap_cons].skb = NULL;
+		BNA_ASSERT(wis >=
+		    BNAD_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags));
+		BNA_ASSERT(((txqinfo->skb_unmap_q.producer_index -
+		    unmap_cons) & (txqinfo->skb_unmap_q.q_depth - 1)) >=
+		    1 + skb_shinfo(skb)->nr_frags);
+
+		sent_packets++;
+		sent_bytes += skb->len;
+		wis -= BNAD_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
+
+		pci_unmap_single(bnad->pcidev,
+		    pci_unmap_addr(&unmap_array[unmap_cons], dma_addr),
+		    skb_headlen(skb), PCI_DMA_TODEVICE);
+		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+		BNA_QE_INDX_ADD(unmap_cons, 1, txqinfo->skb_unmap_q.q_depth);
+		prefetch(&unmap_array[unmap_cons + 1]);
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			pci_unmap_page(bnad->pcidev,
+			    pci_unmap_addr(&unmap_array[unmap_cons], dma_addr),
+			    skb_shinfo(skb)->frags[i].size, PCI_DMA_TODEVICE);
+			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+			    0);
+			BNA_QE_INDX_ADD(unmap_cons, 1,
+			    txqinfo->skb_unmap_q.q_depth);
+			prefetch(&unmap_array[unmap_cons + 1]);
+		}
+		dev_kfree_skb_any(skb);
+	}
+
+	/* Update consumer pointers. */
+	txqinfo->txq.q.consumer_index = updated_txq_cons;
+	txqinfo->skb_unmap_q.consumer_index = unmap_cons;
+	txqinfo->tx_packets += sent_packets;
+	txqinfo->tx_bytes += sent_bytes;
+	return sent_packets;
+}
+
+static int bnad_lro_get_skb_header(struct sk_buff *skb, void **iphdr,
+    void **tcphdr, u64 *hdr_flags, void *priv)
+{
+	struct bna_cq_entry *cmpl = priv;
+	u32 flags = ntohl(cmpl->flags);
+
+	if ((flags & BNA_CQ_EF_IPV4) && (flags & BNA_CQ_EF_TCP)) {
+		skb_reset_network_header(skb);
+		skb_set_transport_header(skb, ip_hdrlen(skb));
+		*iphdr = ip_hdr(skb);
+		*tcphdr = tcp_hdr(skb);
+		*hdr_flags = LRO_IPV4 | LRO_TCP;
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+static inline void bnad_disable_txrx_irqs(struct bnad *bnad)
+{
+	int i;
+
+	for (i = 0; i < bnad->txq_num; i++) {
+		bna_ib_coalescing_timer_set(bnad->priv,
+		    &bnad->txq_table[i].ib, 0);
+		bna_ib_ack(bnad->priv, &bnad->txq_table[i].ib, 0);
+	}
+
+	for (i = 0; i < bnad->cq_num; i++) {
+		bna_ib_coalescing_timer_set(bnad->priv,
+		    &bnad->cq_table[i].ib, 0);
+		bna_ib_ack(bnad->priv, &bnad->cq_table[i].ib, 0);
+	}
+}
+
+static inline void bnad_enable_txrx_irqs(struct bnad *bnad)
+{
+	int i;
+
+	spin_lock_irq(&bnad->priv_lock);
+	for (i = 0; i < bnad->txq_num; i++) {
+		bna_ib_coalescing_timer_set(bnad->priv,
+		    &bnad->txq_table[i].ib, bnad->tx_coalescing_timeo);
+		bna_ib_ack(bnad->priv, &bnad->txq_table[i].ib, 0);
+	}
+
+	for (i = 0; i < bnad->cq_num; i++) {
+		bna_ib_coalescing_timer_set(bnad->priv,
+		    &bnad->cq_table[i].ib,
+			bnad->cq_table[i].rx_coalescing_timeo);
+		bna_ib_ack(bnad->priv, &bnad->cq_table[i].ib, 0);
+	}
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+static inline void
+bnad_disable_rx_irq(struct bnad *bnad, struct bnad_cq_info *cqinfo)
+{
+	bna_ib_coalescing_timer_set(bnad->priv, &cqinfo->ib, 0);
+	bna_ib_ack(bnad->priv, &cqinfo->ib, 0);
+}
+static inline void
+bnad_enable_rx_irq(struct bnad *bnad, struct bnad_cq_info *cqinfo)
+{
+	spin_lock_irq(&bnad->priv_lock);
+
+	bna_ib_coalescing_timer_set(bnad->priv, &cqinfo->ib,
+	    cqinfo->rx_coalescing_timeo);
+	bna_ib_ack(bnad->priv, &cqinfo->ib, 0);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+static unsigned int bnad_tx(struct bnad *bnad, struct bnad_txq_info *txqinfo)
+{
+	struct net_device *netdev = bnad->netdev;
+	unsigned int sent;
+
+	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &txqinfo->flags))
+		return 0;
+
+	DPRINTK(DEBUG, "%s ", netdev->name);
+	DPRINTK(DEBUG, "TxQ hw consumer index %u\n",
+		*txqinfo->hw_consumer_index);
+	 sent = bnad_free_txbufs(txqinfo,
+	    (u16)(*txqinfo->hw_consumer_index));
+	if (sent) {
+		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+		    BNA_Q_FREE_COUNT(&txqinfo->txq) >=
+				BNAD_NETIF_WAKE_THRESHOLD) {
+			netif_wake_queue(netdev);
+			bnad->stats.netif_queue_wakeup++;
+		}
+		bna_ib_ack(bnad->priv, &txqinfo->ib, sent);
+		DPRINTK(DEBUG, "%s ack TxQ IB %u packets\n",
+			netdev->name, sent);
+	} else {
+		bna_ib_ack(bnad->priv, &txqinfo->ib, 0);
+	}
+
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_TXQ_FREE_SENT, &txqinfo->flags);
+
+	return sent;
+}
+
+static irqreturn_t bnad_msix_tx(int irq, void *data)
+{
+	struct bnad_txq_info *txqinfo = (struct bnad_txq_info *)data;
+	struct bnad *bnad = txqinfo->bnad;
+
+
+	bnad_tx(bnad, txqinfo);
+
+	return IRQ_HANDLED;
+}
+
+static void bnad_alloc_rxbufs(struct bnad_rxq_info *rxqinfo)
+{
+	u16 to_alloc, alloced, unmap_prod, wi_range;
+	struct bnad_skb_unmap *unmap_array;
+	struct bna_rxq_entry *rxent;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
+
+	alloced = 0;
+	to_alloc = BNA_QE_FREE_CNT(&rxqinfo->skb_unmap_q,
+	    rxqinfo->skb_unmap_q.q_depth);
+
+	unmap_array = rxqinfo->skb_unmap_q.unmap_array;
+	unmap_prod = rxqinfo->skb_unmap_q.producer_index;
+	BNA_RXQ_QPGE_PTR_GET(unmap_prod, &rxqinfo->rxq.q, rxent, wi_range);
+	BNA_ASSERT(wi_range && wi_range <= rxqinfo->rxq.q.q_depth);
+
+	while (to_alloc--) {
+		if (!wi_range) {
+			BNA_RXQ_QPGE_PTR_GET(unmap_prod, &rxqinfo->rxq.q,
+			    rxent, wi_range);
+			BNA_ASSERT(wi_range &&
+			    wi_range <= rxqinfo->rxq.q.q_depth);
+		}
+		skb = alloc_skb(rxqinfo->rxq_config.buffer_size +
+				BNAD_NET_IP_ALIGN, GFP_ATOMIC);
+		if (unlikely(!skb)) {
+			rxqinfo->rxbuf_alloc_failed++;
+			goto finishing;
+		}
+		skb->dev = rxqinfo->bnad->netdev;
+		skb_reserve(skb, BNAD_NET_IP_ALIGN);
+		unmap_array[unmap_prod].skb = skb;
+		dma_addr = pci_map_single(rxqinfo->bnad->pcidev, skb->data,
+		    rxqinfo->rxq_config.buffer_size, PCI_DMA_FROMDEVICE);
+		pci_unmap_addr_set(&unmap_array[unmap_prod],
+			dma_addr, dma_addr);
+		BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
+		BNA_QE_INDX_ADD(unmap_prod, 1, rxqinfo->skb_unmap_q.q_depth);
+
+		rxent++;
+		wi_range--;
+		alloced++;
+	}
+
+finishing:
+	if (likely(alloced)) {
+		rxqinfo->skb_unmap_q.producer_index = unmap_prod;
+		rxqinfo->rxq.q.producer_index = unmap_prod;
+		smp_mb();
+		bna_rxq_prod_indx_doorbell(&rxqinfo->rxq);
+	}
+}
+
+static inline void bnad_refill_rxq(struct bnad_rxq_info *rxqinfo)
+{
+	if (!test_and_set_bit(BNAD_RXQ_REFILL, &rxqinfo->flags)) {
+		if (BNA_QE_FREE_CNT(&rxqinfo->skb_unmap_q,
+		    rxqinfo->skb_unmap_q.q_depth) >>
+		    BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
+			bnad_alloc_rxbufs(rxqinfo);
+		smp_mb__before_clear_bit();
+		clear_bit(BNAD_RXQ_REFILL, &rxqinfo->flags);
+	}
+}
+
+static unsigned int
+bnad_poll_cq(struct bnad *bnad, struct bnad_cq_info *cqinfo, int budget)
+{
+	struct bna_cq_entry *cmpl, *next_cmpl;
+	unsigned int wi_range, packets = 0, wis = 0;
+	struct bnad_rxq_info *rxqinfo = NULL;
+	struct bnad_unmap_q *unmap_q;
+	struct sk_buff *skb;
+	u32 flags;
+	struct bna_pkt_rate *pkt_rt = &cqinfo->pkt_rate;
+
+	prefetch(bnad);
+	prefetch(bnad->netdev);
+	cmpl = bna_cq_pg_prod_ptr(&cqinfo->cq, &wi_range);
+	BNA_ASSERT(wi_range && wi_range <= cqinfo->cq.q.q_depth);
+	while (cmpl->valid && packets < budget) {
+		packets++;
+		BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
+		rxqinfo = &bnad->rxq_table[cmpl->rxq_id];
+		unmap_q = &rxqinfo->skb_unmap_q;
+		skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
+		BNA_ASSERT(skb);
+		prefetch(skb->data - BNAD_NET_IP_ALIGN);
+		unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+		pci_unmap_single(bnad->pcidev,
+		    pci_unmap_addr(
+		    &unmap_q->unmap_array[unmap_q->consumer_index],
+		    dma_addr),
+		    rxqinfo->rxq_config.buffer_size, PCI_DMA_FROMDEVICE);
+		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
+		/* XXX May be bad for performance. */
+		BNA_Q_CI_ADD(&rxqinfo->rxq, 1);
+		wis++;
+		if (likely(--wi_range)) {
+			next_cmpl = cmpl + 1;
+		} else {
+			BNA_Q_PI_ADD(&cqinfo->cq, wis);
+			wis = 0;
+			next_cmpl = bna_cq_pg_prod_ptr(&cqinfo->cq, &wi_range);
+			BNA_ASSERT(wi_range &&
+			    wi_range <= cqinfo->cq.q.q_depth);
+		}
+		prefetch(next_cmpl);
+
+		flags = ntohl(cmpl->flags);
+		if (unlikely(flags & (BNA_CQ_EF_MAC_ERROR |
+			BNA_CQ_EF_FCS_ERROR | BNA_CQ_EF_TOO_LONG))) {
+			dev_kfree_skb_any(skb);
+			rxqinfo->rx_packets_with_error++;
+			goto next;
+		}
+
+		skb_put(skb, ntohs(cmpl->length));
+		if (likely(bnad->rx_csum &&
+		    (((flags & BNA_CQ_EF_IPV4) &&
+		    (flags & BNA_CQ_EF_L3_CKSUM_OK)) ||
+		    (flags & BNA_CQ_EF_IPV6)) &&
+		    (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) &&
+		    (flags & BNA_CQ_EF_L4_CKSUM_OK)))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb->ip_summed = CHECKSUM_NONE;
+
+		rxqinfo->rx_packets++;
+		rxqinfo->rx_bytes += skb->len;
+		skb->protocol = eth_type_trans(skb, bnad->netdev);
+
+		if (bnad->vlangrp && (flags & BNA_CQ_EF_VLAN) &&
+		    bnad_vlan_strip) {
+			BNA_ASSERT(cmpl->vlan_tag);
+			if (skb->ip_summed == CHECKSUM_UNNECESSARY
+			    && (bnad->netdev->features & NETIF_F_LRO)) {
+				lro_vlan_hwaccel_receive_skb(&cqinfo->lro, skb,
+				    bnad->vlangrp, ntohs(cmpl->vlan_tag), cmpl);
+			} else {
+				vlan_hwaccel_receive_skb(skb, bnad->vlangrp,
+				    ntohs(cmpl->vlan_tag));
+			}
+
+		} else {
+
+			if (skb->ip_summed == CHECKSUM_UNNECESSARY
+			    && (bnad->netdev->features & NETIF_F_LRO))
+				lro_receive_skb(&cqinfo->lro, skb, cmpl);
+			else
+				netif_receive_skb(skb);
+		}
+		bnad->netdev->last_rx = jiffies;
+next:
+		cmpl->valid = 0;
+		cmpl = next_cmpl;
+	}
+
+	lro_flush_all(&cqinfo->lro);
+
+	BNA_Q_PI_ADD(&cqinfo->cq, wis);
+
+	if (likely(rxqinfo)) {
+		bna_ib_ack(bnad->priv, &cqinfo->ib, packets);
+		/* Check the current queue first. */
+		bnad_refill_rxq(rxqinfo);
+
+		/* XXX counters per queue for refill? */
+		if (likely(bnad_small_large_rxbufs)) {
+			/* There are 2 RxQs - small and large buffer queues */
+			unsigned int rxq_id = (rxqinfo->rxq_id ^ 1);
+			bnad_refill_rxq(&bnad->rxq_table[rxq_id]);
+		}
+	} else {
+		bna_ib_ack(bnad->priv, &cqinfo->ib, 0);
+	}
+
+	return packets;
+}
+
+static irqreturn_t bnad_msix_rx(int irq, void *data)
+{
+	struct bnad_cq_info *cqinfo = (struct bnad_cq_info *)data;
+	struct bnad *bnad = cqinfo->bnad;
+
+	if (likely(napi_schedule_prep(&cqinfo->napi))) {
+		bnad_disable_rx_irq(bnad, cqinfo);
+		__napi_schedule(&cqinfo->napi);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bnad_msix_err_mbox(int irq, void *data)
+{
+	struct net_device *netdev = data;
+	struct bnad *bnad = netdev_priv(netdev);
+	u32 intr_status;
+
+	spin_lock(&bnad->priv_lock);
+	bna_intr_status_get(bnad->priv, &intr_status);
+	if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+		DPRINTK(DEBUG, "port %d msix err/mbox irq status 0x%x\n",
+			bnad->bna_id, intr_status);
+		bna_mbox_err_handler(bnad->priv, intr_status);
+	} else {
+		DPRINTK(WARNING, "port %d msix err/mbox irq status 0x%x\n",
+			 bnad->bna_id, intr_status);
+	}
+	spin_unlock(&bnad->priv_lock);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bnad_isr(int irq, void *data)
+{
+	struct net_device *netdev = data;
+	struct bnad *bnad = netdev_priv(netdev);
+	u32 intr_status;
+
+	spin_lock(&bnad->priv_lock);
+	bna_intr_status_get(bnad->priv, &intr_status);
+	spin_unlock(&bnad->priv_lock);
+
+	if (!intr_status)
+		return IRQ_NONE;
+
+	DPRINTK(DEBUG, "port %u bnad_isr: 0x%x\n", bnad->bna_id, intr_status);
+	if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+		spin_lock(&bnad->priv_lock);
+		bna_mbox_err_handler(bnad->priv, intr_status);
+		spin_unlock(&bnad->priv_lock);
+		if (BNA_IS_ERR_INTR(intr_status) ||
+		    !BNA_IS_INTX_DATA_INTR(intr_status))
+			goto exit_isr;
+	}
+
+	if (likely(napi_schedule_prep(&bnad->cq_table[0].napi))) {
+		bnad_disable_txrx_irqs(bnad);
+		__napi_schedule(&bnad->cq_table[0].napi);
+	}
+
+exit_isr:
+	return IRQ_HANDLED;
+}
+
+static int bnad_request_mbox_irq(struct bnad *bnad)
+{
+	int err;
+
+	if (bnad->flags & BNAD_F_MSIX) {
+		DPRINTK(DEBUG,
+			"port %u requests IRQ %u for mailbox in MSI-X mode\n",
+			bnad->bna_id,
+			bnad->msix_table[bnad->msix_num - 1].vector);
+		err = request_irq(bnad->msix_table[bnad->msix_num - 1].vector,
+		    &bnad_msix_err_mbox, 0, bnad->netdev->name,
+		    bnad->netdev);
+	} else {
+		DPRINTK(DEBUG, "port %u requests IRQ %u in INTx mode\n",
+			bnad->bna_id, bnad->pcidev->irq);
+		err = request_irq(bnad->pcidev->irq, &bnad_isr,
+		    IRQF_SHARED, bnad->netdev->name, bnad->netdev);
+	}
+
+	if (err) {
+		dev_err(&bnad->pcidev->dev,
+		    "Request irq for mailbox failed: %d\n", err);
+		return err;
+	}
+
+	if (bnad->flags & BNAD_F_MSIX)
+		bna_mbox_msix_idx_set(bnad->priv, bnad->msix_num - 1);
+
+	bna_mbox_intr_enable(bnad->priv);
+	return 0;
+}
+
+
+static void bnad_sync_mbox_irq(struct bnad *bnad)
+{
+	uint irq;
+
+	if (bnad->flags & BNAD_F_MSIX)
+		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+	else
+		irq = bnad->pcidev->irq;
+	synchronize_irq(irq);
+}
+
+static void bnad_free_mbox_irq(struct bnad *bnad)
+{
+	uint irq;
+
+	if (bnad->flags & BNAD_F_MSIX)
+		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+	else
+		irq = bnad->pcidev->irq;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_mbox_intr_disable(bnad->priv);
+	spin_unlock_irq(&bnad->priv_lock);
+	free_irq(irq, bnad->netdev);
+}
+
+static int bnad_request_txq_irq(struct bnad *bnad, uint txq_id)
+{
+	BNA_ASSERT(txq_id < bnad->txq_num);
+	if (!(bnad->flags & BNAD_F_MSIX))
+		return 0;
+	DPRINTK(DEBUG, "port %u requests irq %u for TxQ %u in MSIX mode\n",
+		bnad->bna_id, bnad->msix_table[txq_id].vector, txq_id);
+	return request_irq(bnad->msix_table[txq_id].vector,
+	    &bnad_msix_tx, 0, bnad->txq_table[txq_id].name,
+	    &bnad->txq_table[txq_id]);
+}
+
+int bnad_request_cq_irq(struct bnad *bnad, uint cq_id)
+{
+	BNA_ASSERT(cq_id < bnad->cq_num);
+	if (!(bnad->flags & BNAD_F_MSIX))
+		return 0;
+	DPRINTK(DEBUG, "port %u requests irq %u for CQ %u in MSIX mode\n",
+		bnad->bna_id,
+		bnad->msix_table[bnad->txq_num + cq_id].vector, cq_id);
+	return request_irq(bnad->msix_table[bnad->txq_num + cq_id].vector,
+	    &bnad_msix_rx, 0, bnad->cq_table[cq_id].name,
+	    &bnad->cq_table[cq_id]);
+}
+
+static void bnad_intx_enable_txrx(struct bnad *bnad)
+{
+	u32 mask;
+	int i;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_intx_disable(bnad->priv, &mask);
+	mask &= ~0xffff;
+	bna_intx_enable(bnad->priv, mask);
+	for (i = 0; i < bnad->ib_num; i++)
+		bna_ib_ack(bnad->priv, bnad->ib_table[i].ib, 0);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+static int bnad_request_txrx_irqs(struct bnad *bnad)
+{
+	struct msix_entry *entries;
+	int i;
+	int err;
+
+	if (!(bnad->flags & BNAD_F_MSIX)) {
+		bnad_intx_enable_txrx(bnad);
+		return 0;
+	}
+
+	entries = bnad->msix_table;
+	for (i = 0; i < bnad->txq_num; i++) {
+		err = bnad_request_txq_irq(bnad, i);
+		if (err) {
+			printk(KERN_ERR "%s request irq for TxQ %d failed %d\n",
+			    bnad->netdev->name, i, err);
+			while (--i >= 0) {
+				free_irq(entries[i].vector,
+				    &bnad->txq_table[i]);
+			}
+			return err;
+		}
+	}
+
+	for (i = 0; i < bnad->cq_num; i++) {
+		err = bnad_request_cq_irq(bnad, i);
+		if (err) {
+			printk(KERN_ERR "%s request irq for CQ %u failed %d\n",
+			    bnad->netdev->name, i, err);
+			while (--i >= 0) {
+				free_irq(entries[bnad->txq_num + i].vector,
+					 &bnad->cq_table[i]);
+			}
+			goto free_txq_irqs;
+		}
+	}
+
+	return 0;
+
+free_txq_irqs:
+	for (i = 0; i < bnad->txq_num; i++)
+		free_irq(entries[i].vector, &bnad->txq_table[i]);
+
+	bnad_disable_msix(bnad);
+
+	return err;
+}
+
+static void bnad_free_txrx_irqs(struct bnad *bnad)
+{
+	struct msix_entry *entries;
+	uint i;
+
+	if (bnad->flags & BNAD_F_MSIX) {
+		entries = bnad->msix_table;
+		for (i = 0; i < bnad->txq_num; i++)
+			free_irq(entries[i].vector, &bnad->txq_table[i]);
+
+		for (i = 0; i < bnad->cq_num; i++)
+			free_irq(entries[bnad->txq_num + i].vector,
+			    &bnad->cq_table[i]);
+	} else {
+		synchronize_irq(bnad->pcidev->irq);
+	}
+}
+
+void bnad_setup_ib(struct bnad *bnad, uint ib_id)
+{
+	struct bnad_ib_entry *ib_entry;
+
+	BNA_ASSERT(ib_id < bnad->ib_num);
+	ib_entry = &bnad->ib_table[ib_id];
+	spin_lock_irq(&bnad->priv_lock);
+	bna_ib_config_set(bnad->priv, ib_entry->ib, ib_id,
+	    &ib_entry->ib_config);
+	/* Start the IB */
+	bna_ib_ack(bnad->priv, ib_entry->ib, 0);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+static void bnad_setup_ibs(struct bnad *bnad)
+{
+	int i;
+
+	for (i = 0; i < bnad->txq_num; i++)
+		bnad_setup_ib(bnad, bnad->txq_table[i].txq_config.ib_id);
+
+	for (i = 0; i < bnad->cq_num; i++)
+		bnad_setup_ib(bnad, bnad->cq_table[i].cq_config.ib_id);
+}
+
+/* These functions are called back with priv_lock held. */
+
+static void bnad_lldp_get_cfg_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = arg;
+	bnad->lldp_comp_status = status;
+	complete(&bnad->lldp_comp);
+}
+
+static void bnad_cee_get_attr_cb(void *arg, bfa_status_t status)
+{
+	struct bnad *bnad = arg;
+	bnad->lldp_comp_status = status;
+	complete(&bnad->lldp_comp);
+}
+
+static void bnad_cee_get_stats_cb(void *arg, bfa_status_t status)
+{
+	struct bnad *bnad = arg;
+	bnad->cee_stats_comp_status = status;
+	complete(&bnad->cee_stats_comp);
+}
+
+static void bnad_cee_reset_stats_cb(void *arg, bfa_status_t status)
+{
+	struct bnad *bnad = arg;
+	bnad->cee_reset_stats_status = status;
+	complete(&bnad->cee_reset_stats_comp);
+}
+
+static void bnad_ucast_set_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+
+	bnad->ucast_comp_status = status;
+	complete(&bnad->ucast_comp);
+}
+
+static void bnad_q_stop_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = arg;
+
+	bnad->qstop_comp_status = status;
+	complete(&bnad->qstop_comp);
+}
+
+static void bnad_link_up_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+	struct net_device *netdev = bnad->netdev;
+
+	DPRINTK(INFO, "%s bnad_link_up_cb\n", netdev->name);
+	if (netif_running(netdev)) {
+		if (!netif_carrier_ok(netdev) &&
+		    !test_bit(BNAD_DISABLED, &bnad->state)) {
+				printk(KERN_INFO "%s link up\n", netdev->name);
+			netif_carrier_on(netdev);
+			bnad->stats.netif_queue_wakeup++;
+		}
+	}
+}
+
+static void bnad_link_down_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+	struct net_device *netdev = bnad->netdev;
+
+	DPRINTK(INFO, "%s bnad_link_down_cb\n", netdev->name);
+	if (netif_running(netdev)) {
+		if (netif_carrier_ok(netdev)) {
+			printk(KERN_INFO "%s link down\n", netdev->name);
+			netif_carrier_off(netdev);
+			bnad->stats.netif_queue_stop++;
+		}
+	}
+}
+
+static void bnad_stats_get_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+
+	bnad->stats.hw_stats_updates++;
+	if (!test_bit(BNAD_DISABLED, &bnad->state))
+		mod_timer(&bnad->stats_timer, jiffies + HZ);
+}
+
+/* Called with bnad priv_lock held. */
+static void bnad_hw_error(struct bnad *bnad, u8 status)
+{
+	unsigned int irq;
+
+	bna_mbox_intr_disable(bnad->priv);
+	if (bnad->flags & BNAD_F_MSIX) {
+		if (!test_and_set_bit(BNAD_MBOX_IRQ_DISABLED, &bnad->state)) {
+			irq = bnad->msix_table[bnad->txq_num +
+			    bnad->cq_num].vector;
+			DPRINTK(WARNING, "Disabling Mbox IRQ %d for port %d\n",
+				irq, bnad->bna_id);
+			disable_irq_nosync(irq);
+		}
+	}
+
+	bna_cleanup(bnad->priv);
+	bnad->work_flags = BNAD_WF_ERROR;
+	if (!test_bit(BNAD_REMOVED, &bnad->state))
+		schedule_work(&bnad->work);
+}
+
+static void bnad_hw_error_cb(void *arg, u8 status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+
+	DPRINTK(WARNING, "port %d HW error callback %u\n",
+		bnad->bna_id, status);
+
+	bnad_hw_error(bnad, status);
+}
+
+int bnad_alloc_unmap_q(struct bnad_unmap_q *unmap_q, u32 q_depth)
+{
+	/* Q_depth must be power of 2 for macros to work. */
+	BNA_ASSERT(BNA_POWER_OF_2(q_depth));
+	unmap_q->q_depth = q_depth;
+	unmap_q->unmap_array = vmalloc(q_depth *
+	    sizeof(struct bnad_skb_unmap));
+	if (!unmap_q->unmap_array)
+		return -ENOMEM;
+	memset(unmap_q->unmap_array, 0,
+	    q_depth * sizeof(struct bnad_skb_unmap));
+	return 0;
+}
+
+static int bnad_alloc_unmap_queues(struct bnad *bnad)
+{
+	int i, err = 0;
+	struct bnad_txq_info *txqinfo;
+	struct bnad_rxq_info *rxqinfo;
+
+	for (i = 0; i < bnad->txq_num; i++) {
+		txqinfo = &bnad->txq_table[i];
+		err = bnad_alloc_unmap_q(&txqinfo->skb_unmap_q,
+		    txqinfo->txq.q.q_depth * 4);
+		DPRINTK(DEBUG, "%s allocating Tx unmap Q %d depth %u\n",
+			bnad->netdev->name, i, txqinfo->txq.q.q_depth * 4);
+		if (err) {
+			DPRINTK(ERR, "%s allocating Tx unmap Q %d failed: %d\n",
+				bnad->netdev->name, i, err);
+			return err;
+		}
+	}
+	for (i = 0; i < bnad->rxq_num; i++) {
+		rxqinfo = &bnad->rxq_table[i];
+		err = bnad_alloc_unmap_q(&rxqinfo->skb_unmap_q,
+		    rxqinfo->rxq.q.q_depth);
+		DPRINTK(INFO, "%s allocating Rx unmap Q %d depth %u\n",
+			bnad->netdev->name, i, rxqinfo->rxq.q.q_depth);
+		if (err) {
+			DPRINTK(ERR, "%s allocating Rx unmap Q %d failed: %d\n",
+				bnad->netdev->name, i, err);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static void
+bnad_reset_q(struct bnad *bnad, struct bna_q *q, struct bnad_unmap_q *unmap_q)
+{
+	u32 _ui;
+	if (q->producer_index != q->consumer_index) {
+		DPRINTK(ERR, "Q producer index %u != ",	q->producer_index);
+		DPRINTK(ERR, "consumer index %u\n", q->consumer_index);
+	}
+	BNA_ASSERT(q->producer_index == q->consumer_index);
+	if (unmap_q->producer_index != unmap_q->consumer_index) {
+		DPRINTK(ERR, "UnmapQ producer index %u != ",
+			unmap_q->producer_index);
+		DPRINTK(ERR, "consumer index %u\n",
+			unmap_q->consumer_index);
+	}
+	BNA_ASSERT(unmap_q->producer_index == unmap_q->consumer_index);
+
+	q->producer_index = 0;
+	q->consumer_index = 0;
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+
+	for (_ui = 0; _ui < unmap_q->q_depth; _ui++)
+		BNA_ASSERT(!unmap_q->unmap_array[_ui].skb);
+}
+
+/* Called with priv_lock. */
+static
+void bnad_flush_rxbufs(struct bnad_rxq_info *rxqinfo)
+{
+	struct bnad *bnad = rxqinfo->bnad;
+	struct bnad_unmap_q *unmap_q;
+	struct sk_buff *skb;
+	u32 cq_id;
+
+	unmap_q = &rxqinfo->skb_unmap_q;
+	while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) {
+		skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
+		BNA_ASSERT(skb);
+		unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+		pci_unmap_single(bnad->pcidev,
+		    pci_unmap_addr(
+		    &unmap_q->unmap_array[unmap_q->consumer_index], dma_addr),
+		    rxqinfo->rxq_config.buffer_size + BNAD_NET_IP_ALIGN,
+		    PCI_DMA_FROMDEVICE);
+		dev_kfree_skb(skb);
+		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
+		BNA_Q_CI_ADD(&rxqinfo->rxq, 1);
+	}
+
+	bnad_reset_q(bnad, &rxqinfo->rxq.q, &rxqinfo->skb_unmap_q);
+	cq_id = rxqinfo->rxq_id / bnad_rxqs_per_cq;
+	*bnad->cq_table[cq_id].hw_producer_index = 0;
+}
+
+static int bnad_disable_txq(struct bnad *bnad, u32 txq_id)
+{
+	struct bnad_txq_info *txqinfo;
+	int err;
+
+	WARN_ON(in_interrupt());
+
+	init_completion(&bnad->qstop_comp);
+	txqinfo = &bnad->txq_table[txq_id];
+	spin_lock_irq(&bnad->priv_lock);
+	err = bna_txq_stop(bnad->priv, txq_id);
+	spin_unlock_irq(&bnad->priv_lock);
+	if (err)
+		goto txq_stop_exit;
+
+	DPRINTK(INFO, "Waiting for %s TxQ %d stop reply\n",
+		bnad->netdev->name, txq_id);
+	wait_for_completion(&bnad->qstop_comp);
+
+	err = bnad->qstop_comp_status;
+txq_stop_exit:
+	if (err)
+		DPRINTK(ERR, "%s bna_txq_stop %d failed %d\n",
+			bnad->netdev->name, txq_id, err);
+	return err;
+}
+
+int bnad_disable_rxqs(struct bnad *bnad, u64 rxq_id_mask)
+{
+	int err;
+
+	struct timeval  tv;
+
+	BNA_ASSERT(!in_interrupt());
+
+	init_completion(&bnad->qstop_comp);
+
+	spin_lock_irq(&bnad->priv_lock);
+	do_gettimeofday(&tv);
+	DPRINTK(DEBUG, "Calling bna_multi_rxq_stop at %ld:%ld\n",
+		tv.tv_sec, tv.tv_usec);
+	err = bna_multi_rxq_stop(bnad->priv, rxq_id_mask);
+	spin_unlock_irq(&bnad->priv_lock);
+	if (err)
+		goto rxq_stop_exit;
+
+	DPRINTK(INFO, "Waiting for %s RxQs(0x%llx) stop reply\n",
+		bnad->netdev->name, rxq_id_mask);
+	wait_for_completion(&bnad->qstop_comp);
+
+	do_gettimeofday(&tv);
+	DPRINTK(DEBUG, "bna_multi_rxq_stop returned at %ld:%ld\n",
+		tv.tv_sec, tv.tv_usec);
+	err = bnad->qstop_comp_status;
+rxq_stop_exit:
+	if (err)
+		DPRINTK(ERR, "%s bna_multi_rxq_stop(0x%llx) failed %d\n",
+			bnad->netdev->name, rxq_id_mask, err);
+	return err;
+
+}
+
+static int bnad_poll_rx(struct napi_struct *napi, int budget)
+{
+	struct bnad_cq_info *cqinfo =
+	    container_of(napi, struct bnad_cq_info, napi);
+	struct bnad *bnad = cqinfo->bnad;
+	unsigned int rcvd;
+
+	rcvd = bnad_poll_cq(bnad, cqinfo, budget);
+	if (rcvd == budget)
+		return rcvd;
+	napi_complete(napi);
+	bnad->stats.netif_rx_complete++;
+	bnad_enable_rx_irq(bnad, cqinfo);
+	return rcvd;
+}
+
+static int bnad_poll_txrx(struct napi_struct *napi, int budget)
+{
+	struct bnad_cq_info *cqinfo =
+	    container_of(napi, struct bnad_cq_info, napi);
+	struct bnad *bnad = cqinfo->bnad;
+	unsigned int rcvd;
+
+	bnad_tx(bnad, &bnad->txq_table[0]);
+	rcvd = bnad_poll_cq(bnad, cqinfo, budget);
+	if (rcvd == budget)
+		return rcvd;
+	napi_complete(napi);
+	bnad->stats.netif_rx_complete++;
+	bnad_enable_txrx_irqs(bnad);
+	return rcvd;
+}
+
+static void bnad_napi_init(struct bnad *bnad)
+{
+	int (*napi_poll)(struct napi_struct *, int);
+	int i;
+
+	if (bnad->flags & BNAD_F_MSIX)
+		napi_poll = bnad_poll_rx;
+	else
+		napi_poll = bnad_poll_txrx;
+
+	for (i = 0; i < bnad->cq_num; i++)
+		netif_napi_add(bnad->netdev, &bnad->cq_table[i].napi,
+		    napi_poll, 64);
+}
+
+static void bnad_napi_enable(struct bnad *bnad)
+{
+	int i;
+
+	for (i = 0; i < bnad->cq_num; i++)
+		napi_enable(&bnad->cq_table[i].napi);
+}
+
+static void bnad_napi_disable(struct bnad *bnad)
+{
+	int i;
+
+	for (i = 0; i < bnad->cq_num; i++)
+		napi_disable(&bnad->cq_table[i].napi);
+}
+
+static void bnad_napi_uninit(struct bnad *bnad)
+{
+	int i;
+
+	for (i = 0; i < bnad->cq_num; i++)
+		netif_napi_del(&bnad->cq_table[i].napi);
+}
+
+
+static void bnad_detach(struct bnad *bnad)
+{
+	int i;
+
+	ASSERT_RTNL();
+
+	spin_lock_irq(&bnad->priv_lock);
+	if (!test_bit(BNAD_RESETTING, &bnad->state)) {
+		/* Graceful detach */
+
+		bna_txf_disable(bnad->priv, BNAD_TX_FUNC_ID);
+		bna_multi_rxf_disable(bnad->priv, (1 << bnad->rxf_num) - 1);
+		for (i = 0; i < bnad->txq_num; i++)
+			bna_ib_disable(bnad->priv, &bnad->txq_table[i].ib);
+		for (i = 0; i < bnad->cq_num; i++)
+			bna_ib_disable(bnad->priv, &bnad->cq_table[i].ib);
+	} else {
+		/* Error */
+		/* XXX Should not write to registers if RESETTING. */
+
+		bna_txf_disable(bnad->priv, BNAD_TX_FUNC_ID);
+		bna_rxf_disable_old(bnad->priv, BNAD_RX_FUNC_ID);
+
+		for (i = 0; i < bnad->txq_num; i++)
+			bna_ib_disable(bnad->priv, &bnad->txq_table[i].ib);
+		for (i = 0; i < bnad->cq_num; i++)
+			bna_ib_disable(bnad->priv, &bnad->cq_table[i].ib);
+	}
+	spin_unlock_irq(&bnad->priv_lock);
+
+	/* Wait to make sure Tx and Rx are stopped. */
+	msleep(1000);
+	bnad_free_txrx_irqs(bnad);
+	bnad_sync_mbox_irq(bnad);
+
+	bnad_napi_disable(bnad);
+	bnad_napi_uninit(bnad);
+
+	/* Delete the stats timer after synchronize with mbox irq. */
+	del_timer_sync(&bnad->stats_timer);
+	netif_tx_disable(bnad->netdev);
+	netif_carrier_off(bnad->netdev);
+}
+
+static int bnad_disable(struct bnad *bnad)
+{
+	int err, i;
+	u64 rxq_id_mask = 0;
+
+	ASSERT_RTNL();
+		DPRINTK(INFO, "bring %s link down\n", bnad->netdev->name);
+		spin_lock_irq(&bnad->priv_lock);
+		bna_port_admin(bnad->priv, BNA_DISABLE);
+		spin_unlock_irq(&bnad->priv_lock);
+
+	bnad_detach(bnad);
+
+	for (i = 0; i < bnad->txq_num; i++) {
+		err = bnad_disable_txq(bnad, i);
+		if (err)
+			return err;
+	}
+
+	for (i = 0; i < bnad->rxq_num; i++)
+		rxq_id_mask |= (1 << i);
+	if (rxq_id_mask) {
+		err = bnad_disable_rxqs(bnad, rxq_id_mask);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+int bnad_sw_reset(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int err;
+
+	if (!netif_running(bnad->netdev))
+		return 0;
+
+	err = bnad_stop_locked(netdev);
+	if (err) {
+		DPRINTK(WARNING, "%s sw reset: disable failed %d\n",
+			bnad->netdev->name, err);
+		/* Recoverable */
+		return 0;
+	}
+
+	err = bnad_open_locked(netdev);
+	if (err) {
+		DPRINTK(WARNING, "%s sw reset: enable failed %d\n",
+			bnad->netdev->name, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int bnad_resetting(struct bnad *bnad)
+{
+	rtnl_lock();
+	if (netif_running(bnad->netdev))
+		bnad_stop_locked(bnad->netdev);
+	set_bit(BNAD_RESETTING, &bnad->state);
+	rtnl_unlock();
+	return 0;
+}
+
+int bnad_alloc_ib(struct bnad *bnad, uint ib_id)
+{
+	struct bnad_ib_entry *ib_entry;
+	dma_addr_t dma_addr;
+
+	BNA_ASSERT(bnad->ib_table && ib_id < bnad->ib_num);
+	ib_entry = &bnad->ib_table[ib_id];
+	ib_entry->ib_seg_addr = pci_alloc_consistent(bnad->pcidev,
+	    L1_CACHE_BYTES, &dma_addr);
+	if (!ib_entry->ib_seg_addr)
+		return -ENOMEM;
+	DPRINTK(DEBUG, "%s IB %d dma addr 0x%llx\n",
+		bnad->netdev->name, ib_id, dma_addr);
+
+	BNA_SET_DMA_ADDR(dma_addr, &ib_entry->ib_config.ib_seg_addr);
+	return 0;
+}
+static int bnad_alloc_ibs(struct bnad *bnad)
+{
+	uint i;
+	int err;
+
+	bnad->ib_num = bnad->txq_num + bnad->cq_num;
+	bnad->ib_table = kzalloc(bnad->ib_num *
+	    sizeof(struct bnad_ib_entry), GFP_KERNEL);
+	if (!bnad->ib_table)
+		return -ENOMEM;
+
+	for (i = 0; i < bnad->ib_num; i++) {
+		err = bnad_alloc_ib(bnad, i);
+		if (err)
+			goto free_ibs;
+	}
+	return 0;
+
+free_ibs:
+	bnad_free_ibs(bnad);
+	return err;
+}
+
+void bnad_free_ib(struct bnad *bnad, uint ib_id)
+{
+	struct bnad_ib_entry *ib_entry;
+	dma_addr_t dma_addr;
+
+	BNA_ASSERT(bnad->ib_table && ib_id < bnad->ib_num);
+	ib_entry = &bnad->ib_table[ib_id];
+	if (ib_entry->ib_seg_addr) {
+		BNA_GET_DMA_ADDR(&ib_entry->ib_config.ib_seg_addr, dma_addr);
+		pci_free_consistent(bnad->pcidev, L1_CACHE_BYTES,
+		    ib_entry->ib_seg_addr, dma_addr);
+		ib_entry->ib_seg_addr = NULL;
+	}
+}
+
+static void bnad_free_ibs(struct bnad *bnad)
+{
+	uint i;
+
+	if (!bnad->ib_table)
+		return;
+
+	for (i = 0; i < bnad->ib_num; i++)
+		bnad_free_ib(bnad, i);
+	kfree(bnad->ib_table);
+	bnad->ib_table = NULL;
+}
+
+/* Let the caller deal with error - free memory. */
+static int bnad_alloc_q(struct bnad *bnad, struct bna_qpt *qpt,
+	struct bna_q *q, size_t qsize)
+{
+	size_t i;
+	dma_addr_t dma_addr;
+
+	qsize = ALIGN(qsize, PAGE_SIZE);
+	qpt->page_count = qsize >> PAGE_SHIFT;
+	qpt->page_size = PAGE_SIZE;
+
+	DPRINTK(DEBUG, "qpt page count 0x%x, ", qpt->page_count);
+	DPRINTK(DEBUG, "page size 0x%x\n", qpt->page_size);
+
+	qpt->kv_qpt_ptr = pci_alloc_consistent(bnad->pcidev,
+	    qpt->page_count * sizeof(struct bna_dma_addr), &dma_addr);
+	if (!qpt->kv_qpt_ptr)
+		return -ENOMEM;
+	BNA_SET_DMA_ADDR(dma_addr, &qpt->hw_qpt_ptr);
+	DPRINTK(DEBUG, "qpt host addr %p, ", qpt->kv_qpt_ptr);
+	DPRINTK(DEBUG, "dma addr 0x%llx\n", dma_addr);
+
+	q->qpt_ptr = kzalloc(qpt->page_count * sizeof(void *), GFP_KERNEL);
+	if (!q->qpt_ptr)
+		return -ENOMEM;
+	qpt->qpt_ptr = q->qpt_ptr;
+	for (i = 0; i < qpt->page_count; i++) {
+		q->qpt_ptr[i] = pci_alloc_consistent(bnad->pcidev, PAGE_SIZE,
+		    &dma_addr);
+		if (!q->qpt_ptr[i])
+			return -ENOMEM;
+		BNA_SET_DMA_ADDR(dma_addr,
+		    &((struct bna_dma_addr *)qpt->kv_qpt_ptr)[i]);
+
+		DPRINTK(DEBUG, "page %d ", (int)i);
+		DPRINTK(DEBUG, "host addr %p, ", q->qpt_ptr[i]);
+		DPRINTK(DEBUG, "dma addr 0x%llx\n", dma_addr);
+	}
+
+	return 0;
+}
+
+static void
+bnad_free_q(struct bnad *bnad, struct bna_qpt *qpt, struct bna_q *q)
+{
+	int i;
+	dma_addr_t dma_addr;
+
+	if (qpt->kv_qpt_ptr && q->qpt_ptr) {
+		for (i = 0; i < qpt->page_count; i++) {
+			if (q->qpt_ptr[i]) {
+				BNA_GET_DMA_ADDR(
+				    &((struct bna_dma_addr *)
+					qpt->kv_qpt_ptr)[i], dma_addr);
+				pci_free_consistent(bnad->pcidev, PAGE_SIZE,
+				    q->qpt_ptr[i], dma_addr);
+			}
+		}
+	}
+
+	kfree(q->qpt_ptr);
+	qpt->qpt_ptr = q->qpt_ptr = NULL;
+
+	if (qpt->kv_qpt_ptr) {
+		BNA_GET_DMA_ADDR(&qpt->hw_qpt_ptr, dma_addr);
+		pci_free_consistent(bnad->pcidev,
+		    qpt->page_count * sizeof(struct bna_dma_addr),
+		    qpt->kv_qpt_ptr, dma_addr);
+		qpt->kv_qpt_ptr = NULL;
+	}
+}
+
+static void bnad_free_txq(struct bnad *bnad, uint txq_id)
+{
+	struct bnad_txq_info *txqinfo;
+
+	BNA_ASSERT(bnad->txq_table && txq_id < bnad->txq_num);
+	txqinfo = &bnad->txq_table[txq_id];
+	bnad_free_q(bnad, &txqinfo->txq_config.qpt, &txqinfo->txq.q);
+	if (txqinfo->skb_unmap_q.unmap_array) {
+		bnad_free_txbufs(txqinfo, txqinfo->txq.q.producer_index);
+		vfree(txqinfo->skb_unmap_q.unmap_array);
+		txqinfo->skb_unmap_q.unmap_array = NULL;
+	}
+}
+
+void bnad_free_rxq(struct bnad *bnad, uint rxq_id)
+{
+	struct bnad_rxq_info *rxqinfo;
+
+	BNA_ASSERT(bnad->rxq_table && rxq_id < bnad->rxq_num);
+	rxqinfo = &bnad->rxq_table[rxq_id];
+	bnad_free_q(bnad, &rxqinfo->rxq_config.qpt, &rxqinfo->rxq.q);
+	if (rxqinfo->skb_unmap_q.unmap_array) {
+		bnad_flush_rxbufs(rxqinfo);
+		vfree(rxqinfo->skb_unmap_q.unmap_array);
+		rxqinfo->skb_unmap_q.unmap_array = NULL;
+	}
+}
+
+void bnad_free_cq(struct bnad *bnad, uint cq_id)
+{
+	struct bnad_cq_info *cqinfo = &bnad->cq_table[cq_id];
+
+	BNA_ASSERT(bnad->cq_table && cq_id < bnad->cq_num);
+	bnad_free_q(bnad, &cqinfo->cq_config.qpt, &cqinfo->cq.q);
+	vfree(cqinfo->lro.lro_arr);
+	cqinfo->lro.lro_arr = NULL;
+}
+
+static void bnad_free_queues(struct bnad *bnad)
+{
+	uint i;
+
+	if (bnad->txq_table) {
+		for (i = 0; i < bnad->txq_num; i++)
+			bnad_free_txq(bnad, i);
+		kfree(bnad->txq_table);
+		bnad->txq_table = NULL;
+	}
+
+	if (bnad->rxq_table) {
+		for (i = 0; i < bnad->rxq_num; i++)
+			bnad_free_rxq(bnad, i);
+		kfree(bnad->rxq_table);
+		bnad->rxq_table = NULL;
+	}
+
+	if (bnad->cq_table) {
+		for (i = 0; i < bnad->cq_num; i++)
+			bnad_free_cq(bnad, i);
+		kfree(bnad->cq_table);
+		bnad->cq_table = NULL;
+	}
+}
+
+static int bnad_txq_init(struct bnad *bnad, uint txq_id)
+{
+	struct bnad_txq_info *txqinfo;
+	int err;
+
+	BNA_ASSERT(bnad->txq_table && txq_id < bnad->txq_num);
+	txqinfo = &bnad->txq_table[txq_id];
+	DPRINTK(DEBUG, "%s allocating TxQ %d\n", bnad->netdev->name, txq_id);
+	err = bnad_alloc_q(bnad, &txqinfo->txq_config.qpt, &txqinfo->txq.q,
+	    bnad->txq_depth * sizeof(struct bna_txq_entry));
+	if (err) {
+		bnad_free_q(bnad, &txqinfo->txq_config.qpt, &txqinfo->txq.q);
+		return err;
+	}
+	txqinfo->txq.q.q_depth = bnad->txq_depth;
+	txqinfo->bnad = bnad;
+	txqinfo->txq_config.txf_id = BNAD_TX_FUNC_ID;
+	snprintf(txqinfo->name, sizeof(txqinfo->name), "%s TxQ %d",
+	    bnad->netdev->name, txq_id);
+	return 0;
+}
+
+static int bnad_txqs_init(struct bnad *bnad)
+{
+	int i, err = 0;
+
+	bnad->txq_table = kzalloc(bnad->txq_num *
+	    sizeof(struct bnad_txq_info), GFP_KERNEL);
+	if (!bnad->txq_table)
+		return -ENOMEM;
+
+	for (i = 0; i < bnad->txq_num; i++) {
+		err = bnad_txq_init(bnad, i);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+int bnad_rxq_init(struct bnad *bnad, uint rxq_id)
+{
+	struct bnad_rxq_info *rxqinfo;
+	int err;
+
+	BNA_ASSERT(bnad->rxq_table && rxq_id < bnad->rxq_num);
+	rxqinfo = &bnad->rxq_table[rxq_id];
+	DPRINTK(DEBUG, "%s allocating RxQ %d\n", bnad->netdev->name, rxq_id);
+	err = bnad_alloc_q(bnad, &rxqinfo->rxq_config.qpt, &rxqinfo->rxq.q,
+	    bnad->rxq_depth * sizeof(struct bna_rxq_entry));
+	if (err) {
+		bnad_free_q(bnad, &rxqinfo->rxq_config.qpt, &rxqinfo->rxq.q);
+		return err;
+	}
+	rxqinfo->rxq.q.q_depth = bnad->rxq_depth;
+	rxqinfo->bnad = bnad;
+	rxqinfo->rxq_id = rxq_id;
+	rxqinfo->rxq_config.cq_id = rxq_id / bnad_rxqs_per_cq;
+
+	return 0;
+}
+
+static int bnad_rxqs_init(struct bnad *bnad)
+{
+	int i, err = 0;
+
+	bnad->rxq_table = kzalloc(bnad->rxq_num *
+	    sizeof(struct bnad_rxq_info), GFP_KERNEL);
+	if (!bnad->rxq_table)
+		return -EINVAL;
+
+	for (i = 0; i < bnad->rxq_num; i++) {
+		err = bnad_rxq_init(bnad, i);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+int bnad_cq_init(struct bnad *bnad, uint cq_id)
+{
+	struct bnad_cq_info *cqinfo;
+	int err;
+
+	BNA_ASSERT(bnad->cq_table && cq_id < bnad->cq_num);
+	cqinfo = &bnad->cq_table[cq_id];
+	DPRINTK(DEBUG, "%s allocating CQ %d\n", bnad->netdev->name, cq_id);
+	err = bnad_alloc_q(bnad, &cqinfo->cq_config.qpt, &cqinfo->cq.q,
+	    bnad->rxq_depth * bnad_rxqs_per_cq * sizeof(struct bna_cq_entry));
+	if (err) {
+		bnad_free_q(bnad, &cqinfo->cq_config.qpt, &cqinfo->cq.q);
+		return err;
+	}
+
+	cqinfo->cq.q.q_depth = bnad->rxq_depth * bnad_rxqs_per_cq;
+	cqinfo->bnad = bnad;
+
+	cqinfo->lro.dev = bnad->netdev;
+	cqinfo->lro.features |= LRO_F_NAPI;
+	if (bnad_vlan_strip)
+		cqinfo->lro.features |= LRO_F_EXTRACT_VLAN_ID;
+	cqinfo->lro.ip_summed = CHECKSUM_UNNECESSARY;
+	cqinfo->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+	cqinfo->lro.max_desc = BNAD_LRO_MAX_DESC;
+	cqinfo->lro.max_aggr = BNAD_LRO_MAX_AGGR;
+	/* XXX */
+	cqinfo->lro.frag_align_pad = 0;
+	cqinfo->lro.lro_arr = vmalloc(BNAD_LRO_MAX_DESC *
+	    sizeof(struct net_lro_desc));
+	if (!cqinfo->lro.lro_arr) {
+		bnad_free_q(bnad, &cqinfo->cq_config.qpt, &cqinfo->cq.q);
+		return err;
+	}
+	memset(cqinfo->lro.lro_arr, 0, BNAD_LRO_MAX_DESC *
+	    sizeof(struct net_lro_desc));
+	cqinfo->lro.get_skb_header = bnad_lro_get_skb_header;
+
+	cqinfo->rx_coalescing_timeo = bnad->rx_coalescing_timeo;
+
+	cqinfo->cq_id = cq_id;
+	snprintf(cqinfo->name, sizeof(cqinfo->name), "%s CQ %d",
+	    bnad->netdev->name, cq_id);
+
+	return 0;
+}
+
+static int bnad_cqs_init(struct bnad *bnad)
+{
+	int i, err = 0;
+
+	bnad->cq_table = kzalloc(bnad->cq_num * sizeof(struct bnad_cq_info),
+	    GFP_KERNEL);
+	if (!bnad->cq_table)
+		return -ENOMEM;
+
+	for (i = 0; i < bnad->cq_num; i++) {
+		err = bnad_cq_init(bnad, i);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+static uint bnad_get_qsize(uint qsize_conf, uint mtu)
+{
+	uint qsize;
+
+	if (mtu > ETH_DATA_LEN) {
+		qsize = qsize_conf / (mtu / ETH_DATA_LEN);
+		if (!BNA_POWER_OF_2(qsize))
+			BNA_TO_POWER_OF_2_HIGH(qsize);
+		if (qsize < BNAD_MIN_Q_DEPTH)
+			qsize = BNAD_MIN_Q_DEPTH;
+	} else
+		qsize = bnad_txq_depth;
+
+	return qsize;
+}
+
+static int bnad_init_queues(struct bnad *bnad)
+{
+	int err;
+
+	if (!(bnad->flags & BNAD_F_TXQ_DEPTH))
+		bnad->txq_depth = bnad_get_qsize(bnad_txq_depth,
+		    bnad->netdev->mtu);
+	if (!(bnad->flags & BNAD_F_RXQ_DEPTH))
+		bnad->rxq_depth = bnad_get_qsize(bnad_rxq_depth,
+		    bnad->netdev->mtu);
+
+	err = bnad_txqs_init(bnad);
+	if (err)
+		return err;
+
+	err = bnad_rxqs_init(bnad);
+	if (err)
+		return err;
+
+	err = bnad_cqs_init(bnad);
+
+	return err;
+}
+
+void bnad_rxib_init(struct bnad *bnad, uint cq_id, uint ib_id)
+{
+	struct bnad_cq_info *cqinfo;
+	struct bnad_ib_entry *ib_entry;
+	struct bna_ib_config *ib_config;
+
+	BNA_ASSERT(cq_id < bnad->cq_num && ib_id < bnad->ib_num);
+	cqinfo = &bnad->cq_table[cq_id];
+	ib_entry = &bnad->ib_table[ib_id];
+
+	cqinfo->hw_producer_index = (u32 *)(ib_entry->ib_seg_addr);
+	cqinfo->cq_config.ib_id = ib_id;
+	cqinfo->cq_config.ib_seg_index = 0;
+
+	ib_entry->ib = &cqinfo->ib;
+	ib_config = &ib_entry->ib_config;
+	ib_config->coalescing_timer = bnad->rx_coalescing_timeo;
+	ib_config->control_flags = BNA_IB_CF_INT_ENABLE |
+	    BNA_IB_CF_MASTER_ENABLE;
+
+	if (bnad->flags & BNAD_F_MSIX) {
+		ib_config->control_flags |= BNA_IB_CF_MSIX_MODE;
+		ib_config->msix_vector = ib_id;
+	} else
+		ib_config->msix_vector = 1 << ib_id;
+
+	/* Every CQ has its own IB. */
+	ib_config->seg_size = 1;
+	ib_config->index_table_offset = ib_id;
+}
+
+static void bnad_ibs_init(struct bnad *bnad)
+{
+	struct bnad_ib_entry *ib_entry;
+	struct bna_ib_config *ib_config;
+	struct bnad_txq_info *txqinfo;
+
+	int ib_id, i;
+
+	ib_id = 0;
+	for (i = 0; i < bnad->txq_num; i++) {
+		txqinfo = &bnad->txq_table[i];
+		ib_entry = &bnad->ib_table[ib_id];
+
+		txqinfo->hw_consumer_index = ib_entry->ib_seg_addr;
+		txqinfo->txq_config.ib_id = ib_id;
+		txqinfo->txq_config.ib_seg_index = 0;
+
+		ib_entry->ib = &txqinfo->ib;
+		ib_config = &ib_entry->ib_config;
+		ib_config->coalescing_timer = bnad->tx_coalescing_timeo;
+		ib_config->control_flags = BNA_IB_CF_INTER_PKT_DMA |
+		    BNA_IB_CF_INT_ENABLE | BNA_IB_CF_COALESCING_MODE |
+		    BNA_IB_CF_MASTER_ENABLE;
+		if (bnad->flags & BNAD_F_MSIX) {
+			ib_config->control_flags |= BNA_IB_CF_MSIX_MODE;
+			ib_config->msix_vector = ib_id;
+		} else
+			ib_config->msix_vector = 1 << ib_id;
+		ib_config->interpkt_count = bnad->tx_interpkt_count;
+
+		/* Every TxQ has its own IB. */
+		ib_config->seg_size = 1;
+		ib_config->index_table_offset = ib_id;
+		ib_id++;
+	}
+
+	for (i = 0; i < bnad->cq_num; i++, ib_id++)
+		bnad_rxib_init(bnad, i, ib_id);
+}
+
+static void bnad_txf_init(struct bnad *bnad, uint txf_id)
+{
+	struct bnad_txf_info *txf_info;
+
+	BNA_ASSERT(bnad->txf_table && txf_id < bnad->txf_num);
+	txf_info = &bnad->txf_table[txf_id];
+	txf_info->txf_id = txf_id;
+	txf_info->txf_config.flags = BNA_TXF_CF_VLAN_WI_BASED |
+	    BNA_TXF_CF_ENABLE;
+}
+
+void bnad_rxf_init(struct bnad *bnad, uint rxf_id, u8 rit_offset, int rss)
+{
+	struct bnad_rxf_info *rxf_info;
+
+	BNA_ASSERT(bnad->rxf_table && rxf_id < bnad->rxf_num);
+	rxf_info = &bnad->rxf_table[rxf_id];
+	rxf_info->rxf_id = rxf_id;
+	rxf_info->rxf_config.rit_offset = rit_offset;
+	rxf_info->rxf_config.mcast_rxq_id = BNAD_MULTICAST_RXQ_ID;
+	if (bnad_small_large_rxbufs)
+		rxf_info->rxf_config.flags |= BNA_RXF_CF_SM_LG_RXQ;
+	if (bnad_vlan_strip)
+		rxf_info->rxf_config.flags |= BNA_RXF_CF_VLAN_STRIP;
+	if (rss) {
+		struct bna_rxf_rss *rxf_rss;
+
+		rxf_info->rxf_config.flags |= BNA_RXF_CF_RSS_ENABLE;
+		rxf_rss = &rxf_info->rxf_config.rss;
+		rxf_rss->type = BNA_RSS_V4_TCP | BNA_RSS_V4_IP |
+		    BNA_RSS_V6_TCP | BNA_RSS_V6_IP;
+		rxf_rss->hash_mask = bnad->cq_num - 1;
+		get_random_bytes(rxf_rss->toeplitz_hash_key,
+		    sizeof(rxf_rss->toeplitz_hash_key));
+	}
+	DPRINTK(DEBUG, "%s RxF %u config flags 0x%x\n",
+		bnad->netdev->name, rxf_id, rxf_info->rxf_config.flags);
+}
+
+static int bnad_init_funcs(struct bnad *bnad)
+{
+	bnad->txf_table = kzalloc(sizeof(struct bnad_txf_info) * bnad->txf_num,
+				  GFP_KERNEL);
+	if (!bnad->txf_table)
+		return -ENOMEM;
+	bnad_txf_init(bnad, BNAD_TX_FUNC_ID);
+
+	bnad->rxf_table = kzalloc(sizeof(struct bnad_rxf_info) * bnad->rxf_num,
+				  GFP_KERNEL);
+	if (!bnad->rxf_table)
+		return -ENOMEM;
+	bnad_rxf_init(bnad, BNAD_RX_FUNC_ID, BNAD_RIT_OFFSET,
+	    (bnad->cq_num > 1) ? 1 : 0);
+	return 0;
+}
+
+static void bnad_setup_txq(struct bnad *bnad, uint txq_id)
+{
+	struct bnad_txq_info *txqinfo;
+
+	BNA_ASSERT(txq_id < bnad->txq_num);
+	txqinfo = &bnad->txq_table[txq_id];
+	txqinfo->txq_config.priority = txq_id;
+	/*  Set wrr_quota properly if multiple priorities/TxQs are enabled. */
+	txqinfo->txq_config.wrr_quota = BNAD_TX_MAX_WRR_QUOTA;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_txq_config(bnad->priv, &txqinfo->txq, txq_id,
+	    &txqinfo->txq_config);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+void bnad_setup_rxq(struct bnad *bnad, uint rxq_id)
+{
+	struct bnad_rxq_info *rxqinfo;
+
+	BNA_ASSERT(rxq_id < bnad->rxq_num);
+	rxqinfo = &bnad->rxq_table[rxq_id];
+	/*
+	 * Every RxQ set has 2 RxQs: the first is large buffer RxQ,
+	 * the second is small buffer RxQ.
+	 */
+	if ((rxq_id % bnad_rxqs_per_cq) == 0)
+		rxqinfo->rxq_config.buffer_size =
+		    (bnad_vlan_strip ? VLAN_ETH_HLEN : ETH_HLEN) +
+		    bnad->netdev->mtu + ETH_FCS_LEN;
+	else
+		rxqinfo->rxq_config.buffer_size = BNAD_SMALL_RXBUF_SIZE;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_rxq_config(bnad->priv, &rxqinfo->rxq, rxq_id,
+	    &rxqinfo->rxq_config);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+void bnad_setup_cq(struct bnad *bnad, uint cq_id)
+{
+	struct bnad_cq_info *cqinfo;
+
+	BNA_ASSERT(cq_id < bnad->cq_num);
+	cqinfo = &bnad->cq_table[cq_id];
+	spin_lock_irq(&bnad->priv_lock);
+	bna_cq_config(bnad->priv, &cqinfo->cq, cq_id,
+	    &cqinfo->cq_config);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+static void bnad_setup_queues(struct bnad *bnad)
+{
+	uint i;
+
+	for (i = 0; i < bnad->txq_num; i++)
+		bnad_setup_txq(bnad, i);
+
+	for (i = 0; i < bnad->rxq_num; i++)
+		bnad_setup_rxq(bnad, i);
+
+	for (i = 0; i < bnad->cq_num; i++)
+		bnad_setup_cq(bnad, i);
+}
+
+
+static void bnad_setup_rit(struct bnad *bnad)
+{
+	int i, size;
+
+	size = bnad->cq_num;
+
+	for (i = 0; i < size; i++) {
+		if (bnad_small_large_rxbufs) {
+			bnad->rit[i].large_rxq_id = (i << 1);
+			bnad->rit[i].small_rxq_id = (i << 1) + 1;
+		} else
+			bnad->rit[i].large_rxq_id = i;
+	}
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_rit_config_set(bnad->priv, BNAD_RIT_OFFSET,
+	    bnad->rit, size);
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+void bnad_alloc_for_rxq(struct bnad *bnad, uint rxq_id)
+{
+	struct bnad_rxq_info *rxqinfo = &bnad->rxq_table[rxq_id];
+	u16 rxbufs;
+
+	BNA_ASSERT(bnad->rxq_table && rxq_id < bnad->rxq_num);
+	bnad_alloc_rxbufs(rxqinfo);
+	rxbufs = BNA_QE_IN_USE_CNT(&rxqinfo->skb_unmap_q,
+	    rxqinfo->skb_unmap_q.q_depth);
+	DPRINTK(INFO, "%s allocated %u rx buffers for RxQ %u\n",
+		bnad->netdev->name, rxbufs, rxq_id);
+}
+
+static int bnad_config_hw(struct bnad *bnad)
+{
+	int i, err;
+	u64 rxq_id_mask = 0;
+	struct sockaddr sa;
+	struct net_device *netdev = bnad->netdev;
+
+	spin_lock_irq(&bnad->priv_lock);
+	/* Disable the RxF until later bringing port up. */
+	bna_multi_rxf_disable(bnad->priv, (1 << bnad->rxf_num) - 1);
+	spin_unlock_irq(&bnad->priv_lock);
+	for (i = 0; i < bnad->txq_num; i++) {
+		err = bnad_disable_txq(bnad, i);
+		if (err)
+			return err;
+	}
+	for (i = 0; i < bnad->rxq_num; i++)
+		rxq_id_mask |= (1 << i);
+	if (rxq_id_mask) {
+		err = bnad_disable_rxqs(bnad, rxq_id_mask);
+		if (err)
+			return err;
+	}
+
+	bnad_setup_queues(bnad);
+
+	bnad_setup_rit(bnad);
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_txf_config_set(bnad->priv, BNAD_TX_FUNC_ID,
+	    &bnad->txf_table->txf_config);
+	for (i = 0; i < bnad->rxf_num; i++) {
+		bna_rxf_config_set(bnad->priv, i,
+		    &bnad->rxf_table[i].rxf_config);
+		bna_rxf_vlan_filter(bnad->priv, i, BNA_ENABLE);
+	}
+	spin_unlock_irq(&bnad->priv_lock);
+
+	/* Mailbox should be enabled before this! */
+	memcpy(sa.sa_data, netdev->dev_addr, netdev->addr_len);
+	bnad_set_mac_address_locked(netdev, &sa);
+
+	spin_lock_irq(&bnad->priv_lock);
+	/* Receive broadcasts */
+	bna_rxf_broadcast(bnad->priv, BNAD_RX_FUNC_ID, BNA_ENABLE);
+
+	bna_mtu_info(bnad->priv, netdev->mtu, bnad);
+	bna_set_pause_config(bnad->priv, &bnad->pause_config, bnad);
+
+	bna_rxf_mcast_del_all(bnad->priv, BNAD_RX_FUNC_ID);
+	bna_mcast_mac_reset_list(bnad->priv);
+	spin_unlock_irq(&bnad->priv_lock);
+
+	bnad_set_rx_mode_locked(bnad->netdev);
+
+	bnad_reconfig_vlans(bnad);
+
+	bnad_setup_ibs(bnad);
+
+	return 0;
+}
+
+/* Note: bnad_cleanup doesn't free irqs */
+static void bnad_cleanup(struct bnad *bnad)
+{
+	kfree(bnad->rit);
+	bnad->rit = NULL;
+	kfree(bnad->txf_table);
+	bnad->txf_table = NULL;
+	kfree(bnad->rxf_table);
+	bnad->rxf_table = NULL;
+
+	bnad_free_ibs(bnad);
+	bnad_free_queues(bnad);
+}
+
+/* Should be called with rtnl_lock held. */
+static int bnad_start(struct bnad *bnad)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	err = bnad_alloc_ibs(bnad);
+	if (err)
+		return err;
+
+	err = bnad_init_queues(bnad);
+	if (err)
+		goto finished;
+
+	bnad_ibs_init(bnad);
+
+	err = bnad_init_funcs(bnad);
+	if (err)
+		goto finished;
+
+	err = bnad_alloc_unmap_queues(bnad);
+	if (err)
+		goto finished;
+
+	bnad->rit = kzalloc(bnad->cq_num * sizeof(struct bna_rit_entry),
+	    GFP_KERNEL);
+
+	if (!bnad->rit)
+		goto finished;
+
+	err = bnad_config_hw(bnad);
+	if (err)
+		goto finished;
+
+		bnad_napi_init(bnad);
+		bnad_napi_enable(bnad);
+
+	err = bnad_request_txrx_irqs(bnad);
+	if (err) {
+		DPRINTK(ERR, "%s requests Tx/Rx irqs failed: %d\n",
+			bnad->netdev->name, err);
+		goto finished;
+	}
+	return 0;
+
+finished:
+	bnad_cleanup(bnad);
+	return err;
+}
+
+int bnad_open_locked(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	uint i;
+	int err;
+
+	ASSERT_RTNL();
+	DPRINTK(WARNING, "%s open\n", netdev->name);
+
+	if (BNAD_NOT_READY(bnad)) {
+		DPRINTK(WARNING, "%s is not ready yet (0x%lx)\n",
+			netdev->name, bnad->state);
+		return -EBUSY;
+	}
+
+	if (!test_bit(BNAD_DISABLED, &bnad->state)) {
+		DPRINTK(WARNING, "%s is already opened (0x%lx)\n",
+			netdev->name, bnad->state);
+		return -EPERM;
+	}
+
+	err = bnad_start(bnad);
+	if (err) {
+		DPRINTK(ERR, "%s failed to start %d\n", netdev->name, err);
+		return err;
+	}
+	for (i = 0; i < bnad->rxq_num; i++)
+		bnad_alloc_for_rxq(bnad, i);
+
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_DISABLED, &bnad->state);
+	DPRINTK(INFO, "%s is opened\n", bnad->netdev->name);
+
+	/* XXX Packet may be come before we bring the port up. */
+	spin_lock_irq(&bnad->priv_lock);
+
+	/* RxF was disabled earlier. */
+	bna_rxf_enable(bnad->priv, BNAD_RX_FUNC_ID);
+	spin_unlock_irq(&bnad->priv_lock);
+
+
+	DPRINTK(INFO, "Bring %s link up\n", netdev->name);
+		spin_lock_irq(&bnad->priv_lock);
+		bna_port_admin(bnad->priv, BNA_ENABLE);
+		spin_unlock_irq(&bnad->priv_lock);
+
+	mod_timer(&bnad->stats_timer, jiffies + HZ);
+
+	return 0;
+}
+
+int bnad_stop_locked(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	ASSERT_RTNL();
+	DPRINTK(WARNING, "%s stop\n", netdev->name);
+
+	if (test_and_set_bit(BNAD_DISABLED, &bnad->state)) {
+		if (BNAD_NOT_READY(bnad)) {
+			DPRINTK(WARNING, "%s is not ready (0x%lx)\n",
+				netdev->name, bnad->state);
+			return -EBUSY;
+		} else {
+			DPRINTK(WARNING, "%s is already stopped (0x%lx)\n",
+				netdev->name, bnad->state);
+			return -EPERM;
+		}
+	}
+
+	bnad_disable(bnad);
+	bnad_cleanup(bnad);
+	DPRINTK(INFO, "%s is stopped\n", bnad->netdev->name);
+	return 0;
+}
+
+int bnad_open(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int error = 0;
+
+	bnad_lock();
+	if (!test_bit(BNAD_PORT_DISABLED, &bnad->state))
+		error = bnad_open_locked(netdev);
+	bnad_unlock();
+	return error;
+}
+
+int bnad_stop(struct net_device *netdev)
+{
+	int error = 0;
+
+	bnad_lock();
+	error = bnad_stop_locked(netdev);
+	bnad_unlock();
+	return error;
+}
+
+static int bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
+{
+	int err;
+
+	BNA_ASSERT(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 ||
+	    skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6);
+
+	if (skb_header_cloned(skb)) {
+		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+		if (err) {
+			bnad->stats.tso_err++;
+			return err;
+		}
+	}
+
+	/*
+	 * For TSO, the TCP checksum field is seeded with pseudo-header sum
+	 * excluding the length field.
+	 */
+	if (skb->protocol == htons(ETH_P_IP)) {
+		struct iphdr *iph = ip_hdr(skb);
+
+		/* Do we really need these? */
+		iph->tot_len = 0;
+		iph->check = 0;
+
+		tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+		    iph->saddr, iph->daddr, 0, IPPROTO_TCP, 0);
+		bnad->stats.tso4++;
+	} else {
+		struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+
+		BNA_ASSERT(skb->protocol == htons(ETH_P_IPV6));
+		ipv6h->payload_len = 0;
+		tcp_hdr(skb)->check = ~csum_ipv6_magic(
+		    &ipv6h->saddr, &ipv6h->daddr, 0, IPPROTO_TCP, 0);
+		bnad->stats.tso6++;
+	}
+
+	return 0;
+}
+
+netdev_tx_t
+bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bnad_txq_info *txqinfo;
+	struct bna_txq *txq;
+	struct bnad_unmap_q *unmap_q;
+	u16 txq_prod;
+	unsigned int unmap_prod, wis, wis_used, wi_range;
+	unsigned int vectors, vect_id, i, acked;
+	int err;
+	dma_addr_t dma_addr;
+	struct bna_txq_entry *txqent;
+	bna_txq_wi_ctrl_flag_t flags;
+
+	if (unlikely(skb->len <= ETH_HLEN ||
+	    skb->len > BNAD_TX_MAX_DATA_PER_WI)) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	txqinfo = &bnad->txq_table[0];
+	txq = &txqinfo->txq;
+	unmap_q = &txqinfo->skb_unmap_q;
+
+	vectors = 1 + skb_shinfo(skb)->nr_frags;
+	if (vectors > BNAD_TX_MAX_VECTORS) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+	wis = BNAD_TXQ_WI_NEEDED(vectors);	/* 4 vectors per work item */
+	acked = 0;
+	if (unlikely(wis > BNA_Q_FREE_COUNT(txq) ||
+	    vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+		if ((u16)(*txqinfo->hw_consumer_index) !=
+		    txq->q.consumer_index &&
+		    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &txqinfo->flags)) {
+			acked = bnad_free_txbufs(txqinfo,
+			    (u16)(*txqinfo->hw_consumer_index));
+			bna_ib_ack(bnad->priv, &txqinfo->ib, acked);
+			DPRINTK(DEBUG, "%s ack TxQ IB %u packets\n",
+				netdev->name, acked);
+			smp_mb__before_clear_bit();
+			clear_bit(BNAD_TXQ_FREE_SENT, &txqinfo->flags);
+		} else
+			netif_stop_queue(netdev);
+
+		smp_mb();
+		/*
+		 * Check again to deal with race condition between
+		 * netif_stop_queue here, and netif_wake_queue in
+		 * interrupt handler which is not inside netif tx lock.
+		 */
+		if (likely(wis > BNA_Q_FREE_COUNT(txq) ||
+		    vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+			bnad->stats.netif_queue_stop++;
+			return NETDEV_TX_BUSY;
+		} else {
+				netif_wake_queue(netdev);
+		}
+	}
+
+	unmap_prod = unmap_q->producer_index;
+	wis_used = 1;
+	vect_id = 0;
+	flags = 0;
+
+	txq_prod = txq->q.producer_index;
+	BNA_TXQ_QPGE_PTR_GET(txq_prod, &txq->q, txqent, wi_range);
+	BNA_ASSERT(wi_range && wi_range <= txq->q.q_depth);
+	txqent->hdr.wi.reserved = 0;
+	txqent->hdr.wi.num_vectors = vectors;
+	txqent->hdr.wi.opcode = htons((skb_is_gso(skb) ?
+	    BNA_TXQ_WI_SEND_LSO : BNA_TXQ_WI_SEND));
+
+	if (bnad_ipid_mode)
+		flags |= BNA_TXQ_WI_CF_IPID_MODE;
+
+	if (bnad->vlangrp && vlan_tx_tag_present(skb)) {
+		u16 vlan_tag = (u16)vlan_tx_tag_get(skb);
+		if ((vlan_tag >> 13) & 0x7)
+			flags |= BNA_TXQ_WI_CF_INS_PRIO;
+		if (vlan_tag & VLAN_VID_MASK)
+			flags |= BNA_TXQ_WI_CF_INS_VLAN;
+		txqent->hdr.wi.vlan_tag = htons(vlan_tag);
+	} else
+		txqent->hdr.wi.vlan_tag = 0;
+
+	if (skb_is_gso(skb)) {
+		err = bnad_tso_prepare(bnad, skb);
+		if (err) {
+			dev_kfree_skb(skb);
+			return NETDEV_TX_OK;
+		}
+		txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
+		flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM);
+		txqent->hdr.wi.l4_hdr_size_n_offset = htons(
+		    BNA_TXQ_WI_L4_HDR_N_OFFSET(tcp_hdrlen(skb) >> 2,
+		    skb_transport_offset(skb)));
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		u8 proto = 0;
+
+		txqent->hdr.wi.lso_mss = 0;
+
+		if (skb->protocol == htons(ETH_P_IP))
+			proto = ip_hdr(skb)->protocol;
+		else if (skb->protocol == htons(ETH_P_IPV6)) {
+			/* XXX the nexthdr may not be TCP immediately. */
+			proto = ipv6_hdr(skb)->nexthdr;
+		}
+		if (proto == IPPROTO_TCP) {
+			flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
+			txqent->hdr.wi.l4_hdr_size_n_offset = htons(
+			    BNA_TXQ_WI_L4_HDR_N_OFFSET(0,
+			    skb_transport_offset(skb)));
+			bnad->stats.tcpcsum_offload++;
+			BNA_ASSERT(skb_headlen(skb) >=
+			    skb_transport_offset(skb) + tcp_hdrlen(skb));
+		} else if (proto == IPPROTO_UDP) {
+			flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
+			txqent->hdr.wi.l4_hdr_size_n_offset = htons(
+			    BNA_TXQ_WI_L4_HDR_N_OFFSET(0,
+			    skb_transport_offset(skb)));
+			bnad->stats.udpcsum_offload++;
+			BNA_ASSERT(skb_headlen(skb) >=
+			    skb_transport_offset(skb) + sizeof(struct udphdr));
+		} else {
+			err = skb_checksum_help(skb);
+			bnad->stats.csum_help++;
+			if (err) {
+				dev_kfree_skb(skb);
+				bnad->stats.csum_help_err++;
+				return NETDEV_TX_OK;
+			}
+		}
+	} else {
+		txqent->hdr.wi.lso_mss = 0;
+		txqent->hdr.wi.l4_hdr_size_n_offset = 0;
+	}
+
+	txqent->hdr.wi.flags = htons(flags);
+
+	txqent->hdr.wi.frame_length = htonl(skb->len);
+
+	unmap_q->unmap_array[unmap_prod].skb = skb;
+	BNA_ASSERT(skb_headlen(skb) <= BNAD_TX_MAX_DATA_PER_VECTOR);
+	txqent->vector[vect_id].length = htons(skb_headlen(skb));
+	dma_addr = pci_map_single(bnad->pcidev, skb->data, skb_headlen(skb),
+	    PCI_DMA_TODEVICE);
+	pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+	    dma_addr);
+	BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+	BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+		if (++vect_id == BNAD_TX_MAX_VECTORS_PER_WI) {
+			vect_id = 0;
+			if (--wi_range)
+				txqent++;
+			else {
+				BNA_QE_INDX_ADD(txq_prod, wis_used,
+				    txq->q.q_depth);
+				wis_used = 0;
+				BNA_TXQ_QPGE_PTR_GET(txq_prod, &txq->q, txqent,
+				    wi_range);
+				BNA_ASSERT(wi_range &&
+				    wi_range <= txq->q.q_depth);
+			}
+			wis_used++;
+			txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION);
+		}
+
+		BNA_ASSERT(frag->size <= BNAD_TX_MAX_DATA_PER_VECTOR);
+		txqent->vector[vect_id].length = htons(frag->size);
+		BNA_ASSERT(unmap_q->unmap_array[unmap_prod].skb == NULL);
+		dma_addr = pci_map_page(bnad->pcidev, frag->page,
+		    frag->page_offset, frag->size, PCI_DMA_TODEVICE);
+		pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+		    dma_addr);
+		BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+	}
+
+	unmap_q->producer_index = unmap_prod;
+	BNA_QE_INDX_ADD(txq_prod, wis_used, txq->q.q_depth);
+	txq->q.producer_index = txq_prod;
+
+	smp_mb();
+	bna_txq_prod_indx_doorbell(txq);
+	netdev->trans_start = jiffies;
+
+	if ((u16)(*txqinfo->hw_consumer_index) !=
+	    txq->q.consumer_index &&
+	    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &txqinfo->flags)) {
+		acked = bnad_free_txbufs(txqinfo,
+		    (u16)(*txqinfo->hw_consumer_index));
+		bna_ib_ack(bnad->priv, &txqinfo->ib, acked);
+		smp_mb__before_clear_bit();
+		clear_bit(BNAD_TXQ_FREE_SENT, &txqinfo->flags);
+	}
+
+	return NETDEV_TX_OK;
+}
+
+struct net_device_stats *bnad_get_stats(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct net_device_stats *net_stats = &bnad->net_stats;
+	struct cna_stats_mac_rx *rxstats = &bnad->hw_stats->mac_rx_stats;
+	struct cna_stats_mac_tx *txstats = &bnad->hw_stats->mac_tx_stats;
+	int i;
+
+	memset(net_stats, 0, sizeof(*net_stats));
+	if (bnad->rxq_table) {
+		for (i = 0; i < bnad->rxq_num; i++) {
+			net_stats->rx_packets += bnad->rxq_table[i].rx_packets;
+			net_stats->rx_bytes += bnad->rxq_table[i].rx_bytes;
+		}
+	}
+	if (bnad->txq_table) {
+		for (i = 0; i < bnad->txq_num; i++) {
+			net_stats->tx_packets += bnad->txq_table[i].tx_packets;
+			net_stats->tx_bytes += bnad->txq_table[i].tx_bytes;
+		}
+	}
+	net_stats->rx_errors = rxstats->rx_fcs_error +
+	    rxstats->rx_alignment_error + rxstats->rx_frame_length_error +
+	    rxstats->rx_code_error + rxstats->rx_undersize;
+	net_stats->tx_errors = txstats->tx_fcs_error + txstats->tx_undersize;
+	net_stats->rx_dropped = rxstats->rx_drop;
+	net_stats->tx_dropped = txstats->tx_drop;
+	net_stats->multicast = rxstats->rx_multicast;
+	net_stats->collisions = txstats->tx_total_collision;
+
+	net_stats->rx_length_errors = rxstats->rx_frame_length_error;
+	net_stats->rx_crc_errors = rxstats->rx_fcs_error;
+	net_stats->rx_frame_errors = rxstats->rx_alignment_error;
+	/* recv'r fifo overrun */
+	net_stats->rx_fifo_errors =
+	    bnad->hw_stats->rxf_stats[0].frame_drops;
+
+	return net_stats;
+}
+
+void bnad_reset_stats(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bnad_rxq_info *rxqinfo;
+	struct bnad_txq_info *txqinfo;
+	int i;
+	memset(&bnad->stats, 0, sizeof(bnad->stats));
+
+	if (bnad->rxq_table) {
+		for (i = 0; i < bnad->rxq_num; i++) {
+			rxqinfo = &bnad->rxq_table[i];
+			rxqinfo->rx_packets = 0;
+			rxqinfo->rx_bytes = 0;
+			rxqinfo->rx_packets_with_error = 0;
+			rxqinfo->rxbuf_alloc_failed = 0;
+		}
+	}
+	if (bnad->txq_table) {
+		for (i = 0; i < bnad->txq_num; i++) {
+			txqinfo = &bnad->txq_table[i];
+			txqinfo->tx_packets = 0;
+			txqinfo->tx_bytes = 0;
+		}
+	}
+}
+
+static void bnad_set_rx_mode_locked(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int err;
+	unsigned long irq_flags;
+
+	if (BNAD_NOT_READY(bnad))
+		return;
+
+	spin_lock_irqsave(&bnad->priv_lock, irq_flags);
+	if (netdev->flags & IFF_PROMISC) {
+		if (!(bnad->flags & BNAD_F_PROMISC)) {
+			bna_rxf_promiscuous(bnad->priv,
+			    BNAD_RX_FUNC_ID, BNA_ENABLE);
+			bnad->flags |= BNAD_F_PROMISC;
+		}
+	} else {
+		if (bnad->flags & BNAD_F_PROMISC) {
+			bna_rxf_promiscuous(bnad->priv,
+			    BNAD_RX_FUNC_ID, BNA_DISABLE);
+			bnad->flags &= ~BNAD_F_PROMISC;
+		}
+	}
+
+	if (netdev->flags & IFF_ALLMULTI) {
+		if (!(bnad->flags & BNAD_F_ALLMULTI)) {
+			bna_rxf_mcast_filter(bnad->priv,
+			    BNAD_RX_FUNC_ID, BNA_DISABLE);
+			bnad->flags |= BNAD_F_ALLMULTI;
+		}
+	} else {
+		if (bnad->flags & BNAD_F_ALLMULTI) {
+			bna_rxf_mcast_filter(bnad->priv,
+			    BNAD_RX_FUNC_ID, BNA_ENABLE);
+			bnad->flags &= ~BNAD_F_ALLMULTI;
+		}
+	}
+	spin_unlock_irqrestore(&bnad->priv_lock, irq_flags);
+
+	if (netdev->mc_count) {
+		u8 *mcaddr_list;
+		u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+		struct dev_mc_list *mc;
+		int i;
+
+		mcaddr_list = kzalloc((netdev->mc_count + 1) *
+		    (ETH_ALEN * sizeof(u8)), GFP_ATOMIC);
+		if (!mcaddr_list)
+			return;
+		memcpy(&mcaddr_list[0], bcast_addr, ETH_ALEN * sizeof(u8));
+
+		mc = netdev->mc_list;
+		for (i = 1; mc && i < netdev->mc_count + 1; i++, mc = mc->next)
+			memcpy(&mcaddr_list[i], mc->dmi_addr,
+				ETH_ALEN * sizeof(u8));
+
+		spin_lock_irqsave(&bnad->priv_lock, irq_flags);
+		err = bna_rxf_mcast_mac_set_list(bnad->priv, BNAD_RX_FUNC_ID,
+		    (const u8 *)mcaddr_list, netdev->mc_count + 1);
+		spin_unlock_irqrestore(&bnad->priv_lock, irq_flags);
+
+		kfree(mcaddr_list);
+	}
+}
+
+static void bnad_set_rx_mode(struct net_device *netdev)
+{
+	bnad_lock();
+	bnad_set_rx_mode_locked(netdev);
+	bnad_unlock();
+}
+
+int bnad_ucast_mac(struct bnad *bnad, unsigned int rxf_id,
+    u8 *mac_ptr, unsigned int cmd)
+{
+	int err = 0;
+	enum bna_status_e (*ucast_mac_func)(struct bna_dev_s *bna_dev,
+		unsigned int rxf_id, const u8 *mac_addr_ptr) = NULL;
+
+	WARN_ON(in_interrupt());
+	if (!is_valid_ether_addr(mac_ptr))
+		return -EINVAL;
+
+	switch (cmd) {
+	case BNAD_UCAST_MAC_SET:
+		ucast_mac_func = bna_rxf_ucast_mac_set;
+		break;
+	case BNAD_UCAST_MAC_ADD:
+		ucast_mac_func = bna_rxf_ucast_mac_add;
+		break;
+	case BNAD_UCAST_MAC_DEL:
+		ucast_mac_func = bna_rxf_ucast_mac_del;
+		break;
+	}
+
+	while (test_and_set_bit(BNAD_SET_UCAST, &bnad->state))
+		msleep(1);
+	init_completion(&bnad->ucast_comp);
+	spin_lock_irq(&bnad->priv_lock);
+	err = ucast_mac_func(bnad->priv, rxf_id, (const u8 *)mac_ptr);
+	spin_unlock_irq(&bnad->priv_lock);
+	if (err)
+		goto ucast_mac_exit;
+
+	DPRINTK(INFO, "Waiting for %s MAC operation %d reply\n",
+		bnad->netdev->name, cmd);
+	wait_for_completion(&bnad->ucast_comp);
+	err = bnad->ucast_comp_status;
+ucast_mac_exit:
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_SET_UCAST, &bnad->state);
+	if (err) {
+		printk(KERN_INFO
+		    "%s unicast MAC address command %d failed: %d\n",
+		    bnad->netdev->name, cmd, err);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bnad_set_mac_address_locked(struct net_device *netdev, void *addr)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct sockaddr *sa = (struct sockaddr *)addr;
+	int err;
+
+	if (!is_valid_ether_addr(sa->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (!BNAD_NOT_READY(bnad)) {
+		err = bnad_ucast_mac(bnad, BNAD_RX_FUNC_ID, (u8 *)sa->sa_data,
+		    BNAD_UCAST_MAC_SET);
+		if (err)
+			return err;
+	}
+
+	memcpy(netdev->dev_addr, sa->sa_data, netdev->addr_len);
+	return 0;
+}
+
+static int bnad_set_mac_address(struct net_device *netdev, void *addr)
+{
+	int err = 0;
+
+	bnad_lock();
+	err = bnad_set_mac_address_locked(netdev, addr);
+	bnad_unlock();
+	return err;
+
+}
+
+static int bnad_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	int err = 0;
+
+	WARN_ON(in_interrupt());
+
+	if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
+		return -EINVAL;
+
+	bnad_lock();
+
+	netdev->mtu = new_mtu;
+
+	err = bnad_sw_reset(netdev);
+
+	bnad_unlock();
+
+	return err;
+}
+
+static int bnad_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	return -EOPNOTSUPP;
+}
+
+static void
+bnad_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	bnad_lock();
+	bnad->vlangrp = grp;
+	bnad_unlock();
+}
+
+static void bnad_vlan_rx_add_vid(struct net_device *netdev, unsigned short vid)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long irq_flags;
+
+	DPRINTK(INFO, "%s add vlan %u\n", netdev->name, vid);
+	bnad_lock();
+	if (BNAD_NOT_READY(bnad)) {
+		bnad_unlock();
+		return;
+	}
+	spin_lock_irqsave(&bnad->priv_lock, irq_flags);
+	bna_rxf_vlan_add(bnad->priv, BNAD_RX_FUNC_ID, (unsigned int)vid);
+	spin_unlock_irqrestore(&bnad->priv_lock, irq_flags);
+	bnad_unlock();
+}
+
+static void
+bnad_vlan_rx_kill_vid(struct net_device *netdev, unsigned short vid)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long irq_flags;
+
+	DPRINTK(INFO, "%s remove vlan %u\n", netdev->name, vid);
+	bnad_lock();
+	if (BNAD_NOT_READY(bnad)) {
+		bnad_unlock();
+		return;
+	}
+	spin_lock_irqsave(&bnad->priv_lock, irq_flags);
+	bna_rxf_vlan_del(bnad->priv, BNAD_RX_FUNC_ID, (unsigned int)vid);
+	spin_unlock_irqrestore(&bnad->priv_lock, irq_flags);
+	bnad_unlock();
+}
+
+static void bnad_reconfig_vlans(struct bnad *bnad)
+{
+	u16 vlan_id;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_rxf_vlan_del_all(bnad->priv, BNAD_RX_FUNC_ID);
+	if (bnad->vlangrp) {
+		for (vlan_id = 0; vlan_id < VLAN_GROUP_ARRAY_LEN; vlan_id++) {
+			if (vlan_group_get_device(bnad->vlangrp, vlan_id))
+				bna_rxf_vlan_add(bnad->priv, BNAD_RX_FUNC_ID,
+				    (unsigned int)vlan_id);
+		}
+	}
+	spin_unlock_irq(&bnad->priv_lock);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void bnad_netpoll(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	DPRINTK(INFO, "%s bnad_netpoll\n", netdev->name);
+	/* Does not address MSIX currently */
+	/* TODO : Fix for MSIX */
+	if (!(bnad->flags & BNAD_F_MSIX)) {
+		disable_irq(bnad->pcidev->irq);
+		bnad_isr(bnad->pcidev->irq, netdev);
+		enable_irq(bnad->pcidev->irq);
+	}
+}
+#endif
+
+static void bnad_q_num_init(struct bnad *bnad, uint rxqsets)
+{
+	bnad->txq_num = BNAD_TXQ_NUM;
+	bnad->txf_num = 1;
+
+	if (bnad->flags & BNAD_F_MSIX) {
+		if (rxqsets) {
+			bnad->cq_num = rxqsets;
+			if (bnad->cq_num > BNAD_MAX_CQS)
+				bnad->cq_num = BNAD_MAX_CQS;
+		} else
+			bnad->cq_num = min((uint)num_online_cpus(),
+			    (uint)BNAD_MAX_RXQSETS_USED);
+		if (!BNA_POWER_OF_2(bnad->cq_num))
+			BNA_TO_POWER_OF_2(bnad->cq_num);
+		bnad->rxq_num = bnad->cq_num * bnad_rxqs_per_cq;
+
+		bnad->rxf_num = 1;
+		bnad->msix_num = bnad->txq_num + bnad->cq_num +
+		    BNAD_MSIX_ERR_MAILBOX_NUM;
+	} else {
+		bnad->cq_num = 1;
+		bnad->rxq_num = bnad->cq_num * bnad_rxqs_per_cq;
+		bnad->rxf_num = 1;
+		bnad->msix_num = 0;
+	}
+}
+
+static void bnad_enable_msix(struct bnad *bnad)
+{
+	int i, ret;
+
+	if (!(bnad->flags & BNAD_F_MSIX) || bnad->msix_table)
+		return;
+
+	bnad->msix_table = kzalloc(
+	    bnad->msix_num * sizeof(struct msix_entry), GFP_KERNEL);
+	if (!bnad->msix_table)
+		goto intx_mode;
+
+	for (i = 0; i < bnad->msix_num; i++)
+		bnad->msix_table[i].entry = i;
+
+	ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
+	    bnad->msix_num);
+	if (ret > 0) {
+		/* Not enough MSI-X vectors. */
+		int rxqsets = ret;
+
+		dev_err(&bnad->pcidev->dev,
+		    "Tried to get %d MSI-X vectors, only got %d\n",
+		    bnad->msix_num, ret);
+		BNA_TO_POWER_OF_2(rxqsets);
+		while (bnad->msix_num > ret && rxqsets) {
+			bnad_q_num_init(bnad, rxqsets);
+			rxqsets >>= 1;
+		}
+		if (bnad->msix_num <= ret) {
+			ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
+			    bnad->msix_num);
+			if (ret) {
+				dev_err(&bnad->pcidev->dev,
+				    "Enabling MSI-X failed: %d\n", ret);
+				goto intx_mode;
+			}
+		} else {
+			dev_err(&bnad->pcidev->dev,
+			    "Enabling MSI-X failed: limited (%d) vectors\n",
+			    ret);
+			goto intx_mode;
+		}
+	} else if (ret < 0) {
+		dev_err(&bnad->pcidev->dev, "Enabling MSI-X failed: %d\n", ret);
+		goto intx_mode;
+	}
+
+	dev_info(&bnad->pcidev->dev,
+	    "Enabling MSI-X succeeded with %d vectors, %s\n", bnad->msix_num,
+	    (bnad->cq_num > 1) ? "RSS is enabled" : "RSS is not enabled");
+	return;
+
+intx_mode:
+	dev_warn(&bnad->pcidev->dev, "Switching to INTx mode with no RSS\n");
+	kfree(bnad->msix_table);
+	bnad->msix_table = NULL;
+	bnad->flags &= ~BNAD_F_MSIX;
+	bnad_q_num_init(bnad, 0);
+}
+
+static void bnad_disable_msix(struct bnad *bnad)
+{
+	if ((bnad->flags & BNAD_F_MSIX) && bnad->msix_table) {
+		pci_disable_msix(bnad->pcidev);
+		kfree(bnad->msix_table);
+		bnad->msix_table = NULL;
+		bnad->flags &= ~BNAD_F_MSIX;
+	}
+}
+
+static void bnad_error(struct bnad *bnad)
+{
+	DPRINTK(INFO, "%s bnad_error\n", bnad->netdev->name);
+
+	rtnl_lock();
+	set_bit(BNAD_RESETTING, &bnad->state);
+	if (!test_and_set_bit(BNAD_DISABLED, &bnad->state)) {
+		bnad_detach(bnad);
+		bnad_cleanup(bnad);
+		DPRINTK(WARNING, "%s is disabled upon error\n",
+			bnad->netdev->name);
+	}
+	rtnl_unlock();
+}
+
+static void bnad_resume_after_reset(struct bnad *bnad)
+{
+	int err;
+	struct net_device *netdev = bnad->netdev;
+
+	DPRINTK(WARNING, "port %d resumes after reset\n", bnad->bna_id);
+
+	rtnl_lock();
+	clear_bit(BNAD_RESETTING, &bnad->state);
+
+	bna_port_mac_get(bnad->priv, (u8 *)bnad->perm_addr);
+	BNA_ASSERT(netdev->addr_len == sizeof(bnad->perm_addr));
+	memcpy(netdev->perm_addr, bnad->perm_addr, netdev->addr_len);
+	if (is_zero_ether_addr(netdev->dev_addr))
+		memcpy(netdev->dev_addr, bnad->perm_addr, netdev->addr_len);
+
+	if (netif_running(bnad->netdev)) {
+		err = bnad_open_locked(bnad->netdev);
+		if (err)
+			DPRINTK(ERR, "%s bnad_open failed after reset: %d\n",
+				bnad->netdev->name, err);
+	}
+	rtnl_unlock();
+}
+
+static void bnad_work(struct work_struct *work)
+{
+	struct bnad *bnad = container_of(work, struct bnad, work);
+	unsigned long work_flags;
+
+	DPRINTK(INFO, "port %u bnad_work flags 0x%x\n",
+		bnad->bna_id, bnad->work_flags);
+
+	spin_lock_irq(&bnad->priv_lock);
+	work_flags = bnad->work_flags;
+	bnad->work_flags = 0;
+	spin_unlock_irq(&bnad->priv_lock);
+
+	if (work_flags & BNAD_WF_ERROR) {
+		DPRINTK(INFO, "port %u bnad_work: BNAD_WF_ERROR\n",
+			bnad->bna_id);
+		bnad_error(bnad);
+	}
+
+	if (work_flags & BNAD_WF_RESETDONE) {
+		DPRINTK(INFO, "port %u bnad_work: BNAD_WF_RESETDONE\n",
+			bnad->bna_id);
+		bnad_resume_after_reset(bnad);
+	}
+}
+
+static void bnad_stats_timeo(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	int i;
+	struct bnad_rxq_info *rxqinfo;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_stats_get(bnad->priv);
+	spin_unlock_irq(&bnad->priv_lock);
+
+	if (bnad->rx_dyn_coalesce_on) {
+		u8 cls_timer;
+		struct bnad_cq_info *cq;
+		for (i = 0; i < bnad->cq_num; i++) {
+			cq = &bnad->cq_table[i];
+
+			if ((cq->pkt_rate.small_pkt_cnt == 0)
+			    && (cq->pkt_rate.large_pkt_cnt == 0))
+				continue;
+
+				cls_timer = bna_calc_coalescing_timer(
+				bnad->priv, &cq->pkt_rate);
+
+			/*For NAPI version, coalescing timer need to stored*/
+			cq->rx_coalescing_timeo = cls_timer;
+
+			bna_ib_coalescing_timer_set(bnad->priv, &cq->ib,
+			    cls_timer);
+		}
+	}
+
+	for (i = 0; i < bnad->rxq_num; i++) {
+		rxqinfo = &bnad->rxq_table[i];
+		if (!(BNA_QE_IN_USE_CNT(&rxqinfo->skb_unmap_q,
+		    rxqinfo->skb_unmap_q.q_depth) >>
+		     BNAD_RXQ_REFILL_THRESHOLD_SHIFT)) {
+			DPRINTK(INFO, "%s: RxQ %d more buffers to allocate\n",
+				bnad->netdev->name, i);
+			if (test_and_set_bit(BNAD_RXQ_REFILL, &rxqinfo->flags))
+				continue;
+			bnad_alloc_rxbufs(rxqinfo);
+			smp_mb__before_clear_bit();
+			clear_bit(BNAD_RXQ_REFILL, &rxqinfo->flags);
+		}
+	}
+}
+
+static void bnad_free_ioc_mem(struct bnad *bnad)
+{
+	enum bna_dma_mem_type i;
+
+	for (i = 0; i < BNA_MEM_T_MAX; i++) {
+		if (!bnad->ioc_meminfo[i].len)
+			continue;
+		if (bnad->ioc_meminfo[i].kva && bnad->ioc_meminfo[i].dma)
+			pci_free_consistent(bnad->pcidev,
+			    bnad->ioc_meminfo[i].len, bnad->ioc_meminfo[i].kva,
+			    *(dma_addr_t *)&bnad->ioc_meminfo[i].dma);
+		else if (bnad->ioc_meminfo[i].kva)
+			vfree(bnad->ioc_meminfo[i].kva);
+		bnad->ioc_meminfo[i].kva = NULL;
+	}
+}
+
+/* The following IOC callback functions are called with priv_lock held. */
+
+void bna_iocll_enable_cbfn(void *arg, enum bfa_status status)
+{
+	struct bnad *bnad = arg;
+
+	DPRINTK(WARNING, "port %u IOC enable callback, status %d\n",
+		bnad->bna_id, status);
+
+	bnad->ioc_comp_status = status;
+	complete(&bnad->ioc_comp);
+
+	if (!status) {
+		bnad->work_flags |= BNAD_WF_RESETDONE;
+		if (!test_bit(BNAD_REMOVED, &bnad->state))
+			schedule_work(&bnad->work);
+	}
+}
+
+void bna_iocll_disable_cbfn(void *arg)
+{
+	struct bnad *bnad = arg;
+
+	DPRINTK(WARNING, "port %u IOC disable callback\n",
+		bnad->bna_id);
+	complete(&bnad->ioc_comp);
+}
+
+void bna_iocll_hbfail_cbfn(void *arg)
+{
+	struct bnad *bnad = arg;
+
+	DPRINTK(ERR, "port %u IOC HBFail callback\n", bnad->bna_id);
+	bnad_hw_error(bnad, BFA_STATUS_IOC_FAILURE);
+}
+
+void bna_iocll_reset_cbfn(void *arg)
+{
+	struct bnad *bnad = arg;
+	u32 int_status, int_mask;
+	unsigned int irq;
+
+	DPRINTK(WARNING, "port %u IOC reset callback\n", bnad->bna_id);
+
+	/* Clear the status */
+	bna_intr_status_get(bnad->priv, &int_status);
+
+	if (bnad->flags & BNAD_F_MSIX) {
+		if (test_and_clear_bit(BNAD_MBOX_IRQ_DISABLED, &bnad->state)) {
+			irq = bnad->msix_table[bnad->txq_num +
+				bnad->cq_num].vector;
+			DPRINTK(WARNING, "Enabling Mbox IRQ %d for port %d\n",
+				irq, bnad->bna_id);
+			enable_irq(irq);
+		}
+	}
+
+	int_mask = ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS);
+	bna_intx_enable(bnad->priv, int_mask);
+}
+
+static void bnad_ioc_timeout(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+
+	spin_lock_irq(&bnad->priv_lock);
+	bna_iocll_timer(bnad->priv);
+	spin_unlock_irq(&bnad->priv_lock);
+
+	if (!test_bit(BNAD_REMOVED, &bnad->state))
+		mod_timer(&bnad->ioc_timer, jiffies +
+			  msecs_to_jiffies(BNA_IOC_TIMER_PERIOD));
+}
+
+s32
+bnad_cee_attach(struct bnad *bnad)
+{
+	u8 *dma_kva;
+	dma_addr_t dma_pa;
+	struct bfa_cee_s *cee = &bnad->cee;
+
+	memset(cee, 0, sizeof(struct bfa_cee_s));
+
+	/*Allocate memory for dma*/
+	dma_kva = pci_alloc_consistent(bnad->pcidev, bfa_cee_meminfo(),
+			    &dma_pa);
+	if (dma_kva == NULL)
+		return -ENOMEM;
+
+	/*Ugly... need to remove once CAL is fixed.*/
+	((struct bna_dev_s *)bnad->priv)->cee = cee;
+
+	bnad->cee_cbfn.get_attr_cbfn = bnad_cee_get_attr_cb;
+	bnad->cee_cbfn.get_stats_cbfn = bnad_cee_get_stats_cb;
+	bnad->cee_cbfn.reset_stats_cbfn = bnad_cee_reset_stats_cb;
+	bnad->cee_cbfn.reset_stats_cbfn = NULL;
+
+	/*Invoke cee attach function*/
+	bfa_cee_attach(cee, &bnad->priv->ioc, bnad,
+	    bnad->trcmod, bnad->logmod);
+	bfa_cee_mem_claim(cee, dma_kva, dma_pa);
+	return 0;
+}
+
+static void
+bnad_cee_detach(struct bnad *bnad)
+{
+	struct bfa_cee_s *cee = &bnad->cee;
+	if (cee->attr_dma.kva) {
+		pci_free_consistent(bnad->pcidev, bfa_cee_meminfo(),
+		    cee->attr_dma.kva, cee->attr_dma.pa);
+	}
+	bfa_cee_detach(&bnad->cee);
+}
+
+
+static int bnad_priv_init(struct bnad *bnad)
+{
+	dma_addr_t dma_addr;
+	struct bna_dma_addr bna_dma_addr;
+	char inst_name[16];
+	int err, i;
+	struct bfa_pcidev_s pcidev_info;
+	u32 intr_mask;
+
+	DPRINTK(DEBUG, "port %u bnad_priv_init\n", bnad->bna_id);
+
+	if (bnad_msix)
+		bnad->flags |= BNAD_F_MSIX;
+	bnad_q_num_init(bnad, bnad_rxqsets_used);
+
+	bnad->work_flags = 0;
+	INIT_WORK(&bnad->work, bnad_work);
+
+	setup_timer(&bnad->stats_timer, bnad_stats_timeo,
+		    (unsigned long)bnad);
+
+	bnad->tx_coalescing_timeo = BNAD_TX_COALESCING_TIMEO;
+	bnad->tx_interpkt_count = BNAD_TX_INTERPKT_COUNT;
+
+	bnad->rx_coalescing_timeo = BNAD_RX_COALESCING_TIMEO;
+	bnad->rx_interpkt_count = BNAD_RX_INTERPKT_COUNT;
+	bnad->rx_interpkt_timeo = BNAD_RX_INTERPKT_TIMEO;
+	bnad->rx_dyn_coalesce_on = BNA_TRUE;
+
+	bnad->rx_csum = 1;
+	bnad->pause_config.tx_pause = 0;
+	bnad->pause_config.rx_pause = 0;
+
+	/* XXX could be vmalloc? */
+	bnad->trcmod = kzalloc(sizeof(struct bfa_trc_mod_s), GFP_KERNEL);
+	if (!bnad->trcmod) {
+		DPRINTK(ERR, "port %u failed allocating trace buffer!\n",
+			bnad->bna_id);
+		return -ENOMEM;
+	}
+	bfa_trc_init(bnad->trcmod);
+
+	bnad->logmod = NULL;
+	sprintf(inst_name, "%u", bnad->bna_id);
+
+	bnad->aen = NULL;
+	INIT_LIST_HEAD(&bnad->file_q);
+	INIT_LIST_HEAD(&bnad->file_free_q);
+	for (i = 0; i < BNAD_AEN_MAX_APPS; i++) {
+		bfa_q_qe_init(&bnad->file_buf[i].qe);
+		list_add_tail(&bnad->file_buf[i].qe, &bnad->file_free_q);
+	}
+
+	bnad->priv = kzalloc(bna_get_handle_size(), GFP_KERNEL);
+	if (!bnad->priv) {
+		DPRINTK(ERR, "port %u failed allocating memory for bna\n",
+			bnad->bna_id);
+		err = -ENOMEM;
+		goto free_trcmod;
+	}
+	bnad->priv_stats = pci_alloc_consistent(bnad->pcidev,
+	    BNA_HW_STATS_SIZE, &dma_addr);
+	if (!bnad->priv_stats) {
+		DPRINTK(ERR, "port %u failed allocating memory for bna stats\n",
+			bnad->bna_id);
+		err = -ENOMEM;
+		goto free_priv_mem;
+	}
+	pci_unmap_addr_set(bnad, priv_stats_dma, dma_addr);
+	DPRINTK(DEBUG, "port %u priv_stats dma addr 0x%llx\n",
+		bnad->bna_id, dma_addr);
+
+	BNA_SET_DMA_ADDR(dma_addr, &bna_dma_addr);
+	bna_init(bnad->priv, (void *)bnad->bar0, bnad->priv_stats,
+	    bna_dma_addr, bnad->trcmod);
+	bna_all_stats_get(bnad->priv, &bnad->hw_stats);
+	spin_lock_init(&bnad->priv_lock);
+	bnad->priv_cbfn.ucast_set_cb = bnad_ucast_set_cb;
+	bnad->priv_cbfn.txq_stop_cb = bnad_q_stop_cb;
+	bnad->priv_cbfn.rxq_stop_cb = bnad_q_stop_cb;
+	bnad->priv_cbfn.link_up_cb = bnad_link_up_cb;
+	bnad->priv_cbfn.link_down_cb = bnad_link_down_cb;
+	bnad->priv_cbfn.stats_get_cb = bnad_stats_get_cb;
+	bnad->priv_cbfn.hw_error_cb = bnad_hw_error_cb;
+	bnad->priv_cbfn.lldp_get_cfg_cb = bnad_lldp_get_cfg_cb;
+
+	bna_register_callback(bnad->priv, &bnad->priv_cbfn, bnad);
+
+	bna_iocll_meminfo(bnad->priv, bnad->ioc_meminfo);
+	for (i = 0; i < BNA_MEM_T_MAX; i++) {
+		if (!bnad->ioc_meminfo[i].len)
+			continue;
+		switch (i) {
+		case BNA_KVA_MEM_T_FWTRC:
+			bnad->ioc_meminfo[i].kva = vmalloc(
+			    bnad->ioc_meminfo[i].len);
+			break;
+		default:
+			bnad->ioc_meminfo[i].kva = pci_alloc_consistent(
+			    bnad->pcidev, bnad->ioc_meminfo[i].len,
+			    (dma_addr_t *)&bnad->ioc_meminfo[i].dma);
+
+			break;
+		}
+		if (!bnad->ioc_meminfo[i].kva) {
+			DPRINTK(ERR,
+				"port %u failed allocating %u bytes"
+				"memory for IOC\n",
+				bnad->bna_id, bnad->ioc_meminfo[i].len);
+			err = -ENOMEM;
+			goto free_ioc_mem;
+		}
+	}
+
+	pcidev_info.pci_slot = PCI_SLOT(bnad->pcidev->devfn);
+	pcidev_info.pci_func = PCI_FUNC(bnad->pcidev->devfn);
+	pcidev_info.device_id = bnad->pcidev->device;
+	pcidev_info.pci_bar_kva = bnad->bar0;
+	bna_iocll_attach(bnad->priv, bnad, bnad->ioc_meminfo,
+	    &pcidev_info, bnad->trcmod, bnad->aen, bnad->logmod);
+
+	err = bnad_cee_attach(bnad);
+	if (err) {
+		DPRINTK(ERR, "port %u cee_attach failed: %d\n",
+			bnad->bna_id, err);
+		goto iocll_detach;
+	}
+
+	if (bnad->flags & BNAD_F_MSIX)
+		bnad_enable_msix(bnad);
+	else
+		dev_info(&bnad->pcidev->dev, "Working in INTx mode, no RSS\n");
+	bna_intx_disable(bnad->priv, &intr_mask);
+	err = bnad_request_mbox_irq(bnad);
+	if (err)
+		goto disable_msix;
+
+	init_completion(&bnad->ioc_comp);
+	DPRINTK(DEBUG, "port %u enabling IOC ...\n", bnad->bna_id);
+	spin_lock_irq(&bnad->priv_lock);
+	bna_iocll_enable(bnad->priv);
+	spin_unlock_irq(&bnad->priv_lock);
+
+	setup_timer(&bnad->ioc_timer, bnad_ioc_timeout,
+		    (unsigned long)bnad);
+	mod_timer(&bnad->ioc_timer, jiffies +
+		  msecs_to_jiffies(BNA_IOC_TIMER_PERIOD));
+
+	DPRINTK(DEBUG, "port %u waiting for IOC ready.\n", bnad->bna_id);
+	wait_for_completion(&bnad->ioc_comp);
+	if (!bnad->ioc_comp_status) {
+		DPRINTK(INFO, "port %u IOC is enabled.\n", bnad->bna_id);
+		bna_port_mac_get(bnad->priv,
+		    (u8 *)bnad->perm_addr);
+	} else {
+		DPRINTK(ERR, "port %u enabling IOC failed: %d\n",
+			bnad->bna_id, bnad->ioc_comp_status);
+		set_bit(BNAD_RESETTING, &bnad->state);
+	}
+
+	return 0;
+
+disable_msix:
+	bnad_disable_msix(bnad);
+	bnad_cee_detach(bnad);
+iocll_detach:
+	bna_iocll_detach(bnad->priv);
+free_ioc_mem:
+	bnad_free_ioc_mem(bnad);
+	bna_uninit(bnad->priv);
+	pci_free_consistent(bnad->pcidev, BNA_HW_STATS_SIZE, bnad->priv_stats,
+	    pci_unmap_addr(bnad, priv_stats_dma));
+	bnad->priv_stats = NULL;
+free_priv_mem:
+	kfree(bnad->priv);
+	bnad->priv = NULL;
+free_trcmod:
+	kfree(bnad->trcmod);
+	bnad->trcmod = NULL;
+
+	return err;
+}
+
+static void bnad_priv_uninit(struct bnad *bnad)
+{
+	int i;
+	enum bna_status_e err;
+
+	if (bnad->priv) {
+		DPRINTK(INFO, "port %u disabling IOC ...\n", bnad->bna_id);
+		init_completion(&bnad->ioc_comp);
+		for (i = 0; i < 10; i++) {
+			spin_lock_irq(&bnad->priv_lock);
+			err = bna_iocll_disable(bnad->priv);
+			spin_unlock_irq(&bnad->priv_lock);
+			BNA_ASSERT(!err || err == BNA_BUSY);
+			if (!err)
+				break;
+			msleep(1000);
+		}
+		if (err) {
+			/* Probably firmware crashed. */
+			DPRINTK(INFO,
+				"bna_iocll_disable failed,"
+				"clean up and try again\n");
+			spin_lock_irq(&bnad->priv_lock);
+			bna_cleanup(bnad->priv);
+			err = bna_iocll_disable(bnad->priv);
+			spin_unlock_irq(&bnad->priv_lock);
+			BNA_ASSERT(!err);
+		}
+		wait_for_completion(&bnad->ioc_comp);
+		set_bit(BNAD_IOC_DISABLED, &bnad->state);
+		DPRINTK(INFO, "port %u IOC is disabled\n", bnad->bna_id);
+
+		set_bit(BNAD_REMOVED, &bnad->state);
+		/* Stop the timer after disabling IOC. */
+		del_timer_sync(&bnad->ioc_timer);
+		bnad_free_ioc_mem(bnad);
+		bna_iocll_detach(bnad->priv);
+
+		flush_scheduled_work();
+		bnad_free_mbox_irq(bnad);
+		bnad_disable_msix(bnad);
+
+		bnad_cee_detach(bnad);
+
+		bna_uninit(bnad->priv);
+		if (bnad->priv_stats) {
+			pci_free_consistent(bnad->pcidev, BNA_HW_STATS_SIZE,
+			    bnad->priv_stats,
+			    pci_unmap_addr(bnad, priv_stats_dma));
+			bnad->priv_stats = NULL;
+		}
+		kfree(bnad->priv);
+		bnad->priv = NULL;
+	}
+	BNA_ASSERT(list_empty(&bnad->file_q));
+	kfree(bnad->trcmod);
+	bnad->trcmod = NULL;
+}
+
+static struct pci_device_id bnad_pci_id_table[] = {
+	{
+	 .vendor = PCI_VENDOR_ID_BROCADE,
+	 .device = PCI_DEVICE_ID_BROCADE_CATAPULT,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 .class = PCI_CLASS_NETWORK_ETHERNET << 8,
+	 .class_mask = 0xffff00
+	},
+	{0, 0}
+};
+MODULE_DEVICE_TABLE(pci, bnad_pci_id_table);
+
+static int __devinit
+bnad_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidev_id)
+{
+	int err, using_dac;
+	struct net_device *netdev;
+	struct bnad *bnad;
+	unsigned long mmio_start, mmio_len;
+	static u32 bna_id;
+
+	DPRINTK(INFO, "bnad_pci_probe(0x%p, 0x%p)\n", pcidev, pcidev_id);
+
+	DPRINTK(DEBUG, "PCI func %d\n", PCI_FUNC(pcidev->devfn));
+	if (!bfad_get_firmware_buf(pcidev)) {
+		printk(KERN_WARNING "Failed to load Firmware Image!\n");
+		return -ENODEV;
+	}
+
+	err = pci_enable_device(pcidev);
+	if (err) {
+		dev_err(&pcidev->dev, "pci_enable_device failed: %d\n", err);
+		return err;
+	}
+
+	err = pci_request_regions(pcidev, BNAD_NAME);
+	if (err) {
+		dev_err(&pcidev->dev, "pci_request_regions failed: %d\n", err);
+		goto disable_device;
+	}
+
+	if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64)) &&
+	    !pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+		using_dac = 1;
+		DPRINTK(INFO, "64bit DMA mask\n");
+	} else {
+		err = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
+		if (err) {
+			err = pci_set_consistent_dma_mask(pcidev,
+							  DMA_BIT_MASK(32));
+			if (err) {
+				dev_err(&pcidev->dev,
+				    "set 32bit consistent DMA mask failed: %d\n"
+					, err);
+				goto release_regions;
+			}
+		}
+		using_dac = 0;
+		DPRINTK(INFO, "32bit DMA mask\n");
+	}
+
+	pci_set_master(pcidev);
+
+	netdev = alloc_etherdev(sizeof(struct bnad));
+	if (!netdev) {
+		dev_err(&pcidev->dev, "alloc_etherdev failed\n");
+		err = -ENOMEM;
+		goto release_regions;
+	}
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pcidev->dev);
+	pci_set_drvdata(pcidev, netdev);
+
+	bnad = netdev_priv(netdev);
+	set_bit(BNAD_DISABLED, &bnad->state);
+	bnad->netdev = netdev;
+	bnad->pcidev = pcidev;
+	mmio_start = pci_resource_start(pcidev, 0);
+	mmio_len = pci_resource_len(pcidev, 0);
+	bnad->bar0 = ioremap_nocache(mmio_start, mmio_len);
+	if (!bnad->bar0) {
+		dev_err(&pcidev->dev, "ioremap for bar0 failed\n");
+		err = -ENOMEM;
+		goto free_devices;
+	}
+	DPRINTK(INFO, "bar0 mapped to %p, len %lu\n", bnad->bar0, mmio_len);
+
+	netdev->netdev_ops = &bnad_netdev_ops;
+	netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
+	netdev->features |= NETIF_F_IPV6_CSUM;
+	netdev->features |= NETIF_F_TSO;
+	netdev->features |= NETIF_F_TSO6;
+	netdev->features |= NETIF_F_LRO;
+	netdev->vlan_features = netdev->features;
+
+	if (using_dac)
+		netdev->features |= NETIF_F_HIGHDMA;
+	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
+	    NETIF_F_HW_VLAN_FILTER;
+
+	netdev->mem_start = mmio_start;
+	netdev->mem_end = mmio_start + mmio_len - 1;
+
+	bnad_set_ethtool_ops(netdev);
+
+	bnad->bna_id = bna_id;
+	err = bnad_priv_init(bnad);
+	if (err) {
+		printk(KERN_ERR "port %u init failed: %d\n", bnad->bna_id, err);
+		goto unmap_bar0;
+	}
+
+	BNA_ASSERT(netdev->addr_len == ETH_ALEN);
+	memcpy(netdev->perm_addr, bnad->perm_addr, netdev->addr_len);
+	memcpy(netdev->dev_addr, bnad->perm_addr, netdev->addr_len);
+
+	netif_carrier_off(netdev);
+	err = register_netdev(netdev);
+	if (err) {
+		printk(KERN_ERR "port %u register_netdev failed: %d\n",
+		    bnad->bna_id, err);
+		goto bnad_device_uninit;
+	}
+
+
+	bna_id++;
+	return 0;
+
+bnad_device_uninit:
+	bnad_priv_uninit(bnad);
+unmap_bar0:
+	iounmap(bnad->bar0);
+free_devices:
+	pci_set_drvdata(pcidev, NULL);
+	free_netdev(netdev);
+release_regions:
+	pci_release_regions(pcidev);
+disable_device:
+	pci_disable_device(pcidev);
+
+	return err;
+}
+
+static void __devexit bnad_pci_remove(struct pci_dev *pcidev)
+{
+	struct net_device *netdev = pci_get_drvdata(pcidev);
+	struct bnad *bnad;
+
+	DPRINTK(INFO, "%s bnad_pci_remove\n", netdev->name);
+	if (!netdev)
+		return;
+	bnad = netdev_priv(netdev);
+
+
+	unregister_netdev(netdev);
+
+	bnad_priv_uninit(bnad);
+	iounmap(bnad->bar0);
+	pci_set_drvdata(pcidev, NULL);
+	free_netdev(netdev);
+	pci_release_regions(pcidev);
+	pci_disable_device(pcidev);
+}
+
+static struct pci_driver bnad_pci_driver = {
+	.name = BNAD_NAME,
+	.id_table = bnad_pci_id_table,
+	.probe    = bnad_pci_probe,
+	.remove   = __devexit_p(bnad_pci_remove),
+};
+
+static int __init bnad_module_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "Brocade 10G Ethernet driver %s\n", bfa_version);
+	DPRINTK(INFO, "Module bna is loaded at 0x%p\n",
+		__this_module.module_core);
+	err = bnad_check_module_params();
+	if (err)
+		return err;
+
+	bfa_ioc_auto_recover(bnad_ioc_auto_recover);
+
+	return pci_register_driver(&bnad_pci_driver);
+}
+
+static void __exit bnad_module_exit(void)
+{
+	pci_unregister_driver(&bnad_pci_driver);
+
+	if (bfi_image_ct_size && bfi_image_ct)
+		vfree(bfi_image_ct);
+}
+
+module_init(bnad_module_init);
+module_exit(bnad_module_exit);
+
+MODULE_AUTHOR("Brocade");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver");
+MODULE_VERSION(BNAD_VERSION);
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bnad.h net-next-2.6-mod/drivers/net/bna/bnad.h
--- net-next-2.6-orig/drivers/net/bna/bnad.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bnad.h	2009-10-31 21:34:47.566535000 -0700
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _BNAD_H_
+#define _BNAD_H_
+
+#include <cee/bfa_cee.h>
+#include "bna.h"
+
+#if !defined(CONFIG_INET_LRO) && !defined(CONFIG_INET_LRO_MODULE)
+#include <net/ip.h>
+#include <net/tcp.h>
+#else
+#include <linux/inet_lro.h>
+#endif
+
+#include "bnad_compat.h"
+
+#define BNAD_LRO_MAX_DESC	8
+#define BNAD_LRO_MAX_AGGR	64
+
+
+#define BNAD_MAX_Q_DEPTH	0x10000
+#define BNAD_MIN_Q_DEPTH	0x200
+
+#define BNAD_TXQ_NUM		1
+#define BNAD_TX_FUNC_ID		0
+#define BNAD_ENTRIES_PER_TXQ	2048
+
+#define BNAD_MAX_RXQS		64
+#define BNAD_MAX_RXQSETS_USED	16
+#define BNAD_RX_FUNC_ID		0
+#define BNAD_ENTRIES_PER_RXQ	2048
+
+#define BNAD_MAX_CQS		64
+#define BNAD_MAX_RXQS_PER_CQ	2
+
+#define BNAD_MSIX_ERR_MAILBOX_NUM	1
+
+#define BNAD_INTX_MAX_IB_NUM	16
+#define BNAD_INTX_IB_NUM	2	/* 1 for Tx, 1 for Rx */
+#define BNAD_INTX_TX_IB_ID	0
+#define BNAD_INTX_RX_IB_ID	1
+
+#define BNAD_QUEUE_NAME_SIZE	16
+
+#define BNAD_JUMBO_MTU		9000
+
+#define BNAD_COALESCING_TIMER_UNIT	5	/* 5us */
+#define BNAD_MAX_COALESCING_TIMEO	0xFF 	/* in 5us units */
+#define BNAD_MAX_INTERPKT_COUNT		0xFF
+#define BNAD_MAX_INTERPKT_TIMEO		0xF	/* in 0.5us units */
+
+#define BNAD_TX_COALESCING_TIMEO	20	/* 20 * 5 = 100us */
+#define BNAD_TX_INTERPKT_COUNT		32
+
+#define BNAD_RX_COALESCING_TIMEO	12	/* 12 * 5 = 60us */
+#define BNAD_RX_INTERPKT_COUNT		6
+#define BNAD_RX_INTERPKT_TIMEO		3	/* 3 * 0.5 = 1.5us */
+
+#define BNAD_SMALL_RXBUF_SIZE	128
+
+#define BNAD_RIT_OFFSET		0
+#define BNAD_MULTICAST_RXQ_ID	0
+
+#define BNAD_NETIF_WAKE_THRESHOLD	8
+
+#define BNAD_TX_MAX_VECTORS		255
+#define BNAD_TX_MAX_VECTORS_PER_WI	4
+#define BNAD_TX_MAX_DATA_PER_WI		0xFFFFFF	/* 24 bits */
+#define BNAD_TX_MAX_DATA_PER_VECTOR	0x3FFF		/* 14 bits */
+#define BNAD_TX_MAX_WRR_QUOTA		0xFFF		/* 12 bits */
+
+#define BNAD_RXQ_REFILL_THRESHOLD_SHIFT	3
+
+#define BNAD_CQ_PROCESS_LIMIT		512
+
+#define BNAD_NOT_READY(_bnad)	test_bit(BNAD_RESETTING, &(_bnad)->state)
+
+#define BNAD_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth)	\
+    (((_updated_idx) - (_old_idx)) & ((_q_depth) - 1))
+
+#define bnad_lock()
+#define bnad_unlock()
+
+extern u32 bfi_image_ct_size;
+extern u32 *bfi_image_ct;
+extern u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
+
+struct bnad_skb_unmap {
+	struct sk_buff *skb;
+	DECLARE_PCI_UNMAP_ADDR(dma_addr)
+};
+
+struct bnad_unmap_q {
+    u32    producer_index;
+    u32    consumer_index;
+    struct bnad_skb_unmap *unmap_array;
+    u32	q_depth;
+};
+
+struct bnad_ib_entry {
+	struct bna_ib *ib;
+	void *ib_seg_addr;
+	struct bna_ib_config ib_config;
+};
+
+struct bnad_txq_info {
+	unsigned long flags;
+#define BNAD_TXQ_FREE_SENT	0
+	struct bna_txq txq;
+	struct bna_ib ib;
+	struct bnad_unmap_q skb_unmap_q;
+	u64 tx_packets;
+	u64 tx_bytes;
+	struct bnad *bnad;
+	volatile u32 *hw_consumer_index;
+	struct bna_txq_config txq_config;
+	char name[BNAD_QUEUE_NAME_SIZE];
+#ifdef DEBUG_TX
+	u32 max_tso;
+	u32 tx_vectors[32];
+#endif
+} ____cacheline_aligned;
+
+struct bnad_rxq_info {
+	unsigned long flags;
+#define BNAD_RXQ_REFILL		0
+	struct bna_rxq rxq;
+	struct bnad_unmap_q skb_unmap_q;
+	u64 rx_packets;
+	u64 rx_bytes;
+	u64 rx_packets_with_error;
+	u64 rxbuf_alloc_failed;
+	struct bnad *bnad;
+	u32 rxq_id;
+	struct bna_rxq_config rxq_config;
+}  ____cacheline_aligned;
+
+struct bnad_cq_info {
+	struct bna_cq cq;
+	struct bna_ib ib;
+	struct bnad *bnad;
+	struct bna_pkt_rate pkt_rate;
+	u8 rx_coalescing_timeo;	/* Unit is 5usec. */
+	volatile u32 *hw_producer_index;
+	struct net_lro_mgr  lro;
+	struct napi_struct napi;
+	u32 cq_id;
+	struct bna_cq_config cq_config;
+	char name[BNAD_QUEUE_NAME_SIZE];
+}  ____cacheline_aligned;
+
+struct bnad_txf_info {
+	u32 txf_id;
+	struct bna_txf_config txf_config;
+};
+
+struct bnad_rxf_info {
+	u32 rxf_id;
+	struct bna_rxf_config rxf_config;
+};
+
+enum bnad_ucast_cmd {
+	BNAD_UCAST_MAC_SET,
+	BNAD_UCAST_MAC_ADD,
+	BNAD_UCAST_MAC_DEL
+};
+
+struct bnad_diag_lb_params {
+	struct bnad *bnad;
+	struct completion diag_lb_comp;
+	int diag_lb_comp_status;
+	int diag_lb_link_state;
+#define BNAD_DIAG_LB_LS_UNKNOWN	-1
+#define BNAD_DIAG_LB_LS_UP	 0
+#define BNAD_DIAG_LB_LS_DOWN	 1
+};
+
+#define BNAD_AEN_MAX_APPS 8
+struct bnad_aen_file_s {
+	struct list_head  qe;
+	struct bnad *bnad;
+	s32 ri;
+	s32 app_id;
+};
+
+struct bnad {
+	struct net_device *netdev;
+	struct pci_dev *pcidev;
+	struct bna_dev_s *priv;
+
+	unsigned long state;
+#define BNAD_DISABLED		0
+#define BNAD_RESETTING		1
+#define BNAD_REMOVED		2
+#define BNAD_SET_UCAST		4
+#define BNAD_IOC_DISABLED	5
+#define BNAD_PORT_DISABLED	6
+#define BNAD_MBOX_IRQ_DISABLED	7
+
+	unsigned int flags;
+#define BNAD_F_MSIX		0x01
+#define BNAD_F_PROMISC		0x02
+#define BNAD_F_ALLMULTI		0x04
+#define BNAD_F_WOL		0x08
+#define BNAD_F_TXQ_DEPTH	0x10
+#define BNAD_F_RXQ_DEPTH	0x20
+
+
+	uint txq_num;
+	uint txq_depth;
+	struct bnad_txq_info *txq_table;
+	uint rxq_num;
+	uint rxq_depth;
+	struct bnad_rxq_info *rxq_table;
+	uint cq_num;
+	struct bnad_cq_info *cq_table;
+
+	struct vlan_group *vlangrp;
+
+	u32 rx_csum;
+
+	uint msix_num;
+	struct msix_entry *msix_table;
+
+	uint ib_num;
+	struct bnad_ib_entry *ib_table;
+
+	struct bna_rit_entry *rit;		/* RxQ Indirection Table */
+
+	spinlock_t priv_lock ____cacheline_aligned;
+
+	uint txf_num;
+	struct bnad_txf_info *txf_table;
+	uint rxf_num;
+	struct bnad_rxf_info *rxf_table;
+
+	struct timer_list stats_timer;
+	struct net_device_stats net_stats;
+
+	u8 tx_coalescing_timeo;	/* Unit is 5usec. */
+	u8 tx_interpkt_count;
+
+	u8 rx_coalescing_timeo;	/* Unit is 5usec. */
+	u8 rx_interpkt_count;
+	u8	rx_interpkt_timeo;	/* 4 bits, unit is 0.5usec. */
+	u8 rx_dyn_coalesce_on;	/* Rx Dynamic Intr Moderation Flag */
+	u8 ref_count;
+	u8 lldp_comp_status;
+	u8 cee_stats_comp_status;
+	u8 cee_reset_stats_status;
+	u8 ucast_comp_status;
+	u8 qstop_comp_status;
+	u16 rsvd_2;
+	int ioc_comp_status;
+
+	struct bna_pause_config pause_config;
+
+	struct bna_stats *hw_stats;
+	struct bnad_drv_stats stats;
+
+	struct work_struct work;
+	unsigned int work_flags;
+#define BNAD_WF_ERROR		0x1
+#define BNAD_WF_RESETDONE	0x2
+
+	struct completion lldp_comp;
+	struct completion cee_stats_comp;
+	struct completion cee_reset_stats_comp;
+	struct completion ucast_comp;
+	struct completion qstop_comp;
+	struct completion ioc_comp;
+
+	u32 bna_id;
+	u8 __iomem *bar0;			/* registers */
+	unsigned char perm_addr[ETH_ALEN];
+	u32 pci_saved_config[16];
+
+	void *priv_stats;
+	DECLARE_PCI_UNMAP_ADDR(priv_stats_dma)
+
+	struct bfa_trc_mod_s *trcmod;
+	struct bfa_log_mod_s *logmod;
+	struct bfa_aen_s *aen;
+	struct bnad_aen_file_s file_buf[BNAD_AEN_MAX_APPS];
+	struct list_head         file_q;
+	struct list_head         file_free_q;
+	struct bna_meminfo ioc_meminfo[BNA_MEM_T_MAX];
+	struct timer_list ioc_timer;
+
+	struct bna_mbox_cbfn priv_cbfn;
+
+	char adapter_name[64];
+	char port_name[64];
+
+	/* Diagnostics */
+	struct bna_diag_lb_pkt_stats *lb_stats;
+	struct bnad_diag_lb_params *dlbp;
+
+	/* CEE Stuff */
+	struct bfa_cee_cbfn_s cee_cbfn;
+	struct bfa_cee_s cee;
+
+	struct list_head list_entry;
+};
+
+extern uint bnad_rxqs_per_cq;
+extern uint bnad_rxq_depth;
+extern uint bnad_txq_depth;
+extern uint bnad_small_large_rxbufs;
+
+extern struct list_head bnad_list;
+
+int bnad_open(struct net_device *netdev);
+int bnad_stop(struct net_device *netdev);
+int bnad_stop_locked(struct net_device *netdev);
+int bnad_open_locked(struct net_device *netdev);
+int bnad_sw_reset(struct net_device *netdev);
+int bnad_resetting(struct bnad *bnad);
+void bnad_set_ethtool_ops(struct net_device *netdev);
+void bnad_ioctl_init(void);
+void bnad_ioctl_exit(void);
+struct net_device_stats *bnad_get_stats(struct net_device *netdev);
+void bnad_reset_stats(struct net_device *netdev);
+
+int bnad_ucast_mac(struct bnad *bnad, unsigned int rxf_id,
+		   u8 *mac_ptr, unsigned int cmd);
+int bnad_rxq_init(struct bnad *bnad, uint rxq_id);
+void bnad_setup_rxq(struct bnad *bnad, uint rxq_id);
+void bnad_alloc_for_rxq(struct bnad *bnad, uint rxq_id);
+void bnad_free_rxq(struct bnad *bnad, uint rxq_id);
+int bnad_cq_init(struct bnad *bnad, uint cq_id);
+void bnad_setup_cq(struct bnad *bnad, uint cq_id);
+int bnad_alloc_ib(struct bnad *bnad, uint ib_id);
+void bnad_setup_ib(struct bnad *bnad, uint ib_id);
+void bnad_rxib_init(struct bnad *bnad, uint cq_id, uint ib_id);
+void bnad_free_ib(struct bnad *bnad, uint ib_id);
+int bnad_request_cq_irq(struct bnad *bnad, uint cq_id);
+u32 bnad_get_msglevel(struct net_device *netdev);
+void bnad_set_msglevel(struct net_device *netdev, u32 msglevel);
+int bnad_alloc_unmap_q(struct bnad_unmap_q *unmap_q, u32 q_depth);
+int bnad_disable_rxq(struct bnad *bnad, u32 rxq_id);
+void bnad_free_cq(struct bnad *bnad, uint cq_id);
+void bnad_add_to_list(struct bnad *bnad);
+void bnad_remove_from_list(struct bnad *bnad);
+struct bnad *get_bnadev(int bna_id);
+/* For diagnostics */
+int bnad_diag_lb_rx(struct bnad *bnad, struct sk_buff *skb);
+int bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev);
+
+#endif /* _BNAD_H_ */

^ permalink raw reply

* Subject: [PATCH 5/6] bna: Brocade 10Gb Ethernet device driver
From: Rasesh Mody @ 2009-11-01  5:03 UTC (permalink / raw)
  To: netdev; +Cc: adapter_linux_open_src_team

From: Rasesh Mody <rmody@brocade.com>

This is patch 5/6 which contains linux driver source for
Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
Re-based source against net-next-2.6 and re-submitting the
patch with few fixes.

We wish this patch to be considered for inclusion in net-next-2.6

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 bfa_callback_priv.h               |   64 +++
 bfa_fwimg_priv.h                  |   38 ++
 include/bfi/bfi.h                 |  181 +++++++++++
 include/bfi/bfi_boot.h            |   41 ++
 include/bfi/bfi_cee.h             |  119 +++++++
 include/bfi/bfi_ctreg.h           |  611 ++++++++++++++++++++++++++++++++++++++
 include/bfi/bfi_ioc.h             |  209 ++++++++++++
 include/bfi/bfi_ll.h              |  443 +++++++++++++++++++++++++++
 include/cee/bfa_cee.h             |   82 +++++
 include/cna/pstats/ethport_defs.h |   43 ++
 include/cna/pstats/phyport_defs.h |  225 +++++++++++++
 include/cs/bfa_debug.h            |   51 +++
 include/cs/bfa_q.h                |   88 +++++
 include/cs/bfa_sm.h               |   76 ++++
 include/cs/bfa_trc.h              |   67 ++++
 include/defs/bfa_defs_adapter.h   |   89 +++++
 include/defs/bfa_defs_cee.h       |  165 ++++++++++
 include/defs/bfa_defs_ioc.h       |  158 +++++++++
 include/defs/bfa_defs_mfg.h       |   65 ++++
 include/defs/bfa_defs_pci.h       |   48 ++
 include/defs/bfa_defs_status.h    |  262 ++++++++++++++++
 include/defs/bfa_defs_types.h     |   37 ++
 include/defs/bfa_defs_version.h   |   29 +
 include/protocol/types.h          |   49 +++
 24 files changed, 3240 insertions(+)

diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_callback_priv.h net-next-2.6-mod/drivers/net/bna/bfa_callback_priv.h
--- net-next-2.6-orig/drivers/net/bna/bfa_callback_priv.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_callback_priv.h	2009-10-31 21:34:48.455462000 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFA_CALLBACK_PRIV_H__
+#define __BFA_CALLBACK_PRIV_H__
+
+#include <cs/bfa_q.h>
+
+typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/**
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+	struct list_head         qe;
+	bfa_cb_cbfn_t  cbfn;
+	bfa_boolean_t   once;
+	u32		rsvd;
+	void           *cbarg;
+};
+
+#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {		\
+	(__hcb_qe)->cbfn  = (__cbfn);      \
+	(__hcb_qe)->cbarg = (__cbarg);      \
+	list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
+} while (0)
+
+#define bfa_cb_dequeue(__hcb_qe)	list_del(&(__hcb_qe)->qe)
+
+#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
+	(__hcb_qe)->cbfn  = (__cbfn);      \
+	(__hcb_qe)->cbarg = (__cbarg);      \
+	if (!(__hcb_qe)->once) {      \
+		list_add_tail((__hcb_qe), &(__bfa)->comp_q);      \
+		(__hcb_qe)->once = BFA_TRUE;				\
+	}								\
+} while (0)
+
+#define bfa_cb_queue_done(__hcb_qe) do {				\
+	(__hcb_qe)->once = BFA_FALSE;					\
+} while (0)
+
+#endif /* __BFA_CALLBACK_PRIV_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_fwimg_priv.h net-next-2.6-mod/drivers/net/bna/bfa_fwimg_priv.h
--- net-next-2.6-orig/drivers/net/bna/bfa_fwimg_priv.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_fwimg_priv.h	2009-10-31 21:34:48.461464000 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFA_FWIMG_PRIV_H__
+#define __BFA_FWIMG_PRIV_H__
+
+#define	BFI_FLASH_CHUNK_SZ		256	/*  Flash chunk size */
+#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
+
+extern u32 *bfi_image_ct_get_chunk(u32 off);
+extern u32 bfi_image_ct_size;
+extern u32 *bfi_image_cb_get_chunk(u32 off);
+extern u32 bfi_image_cb_size;
+extern u32 *bfi_image_cb;
+extern u32 *bfi_image_ct;
+
+#endif /* __BFA_FWIMG_PRIV_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/bfi/bfi.h net-next-2.6-mod/drivers/net/bna/include/bfi/bfi.h
--- net-next-2.6-orig/drivers/net/bna/include/bfi/bfi.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/bfi/bfi.h	2009-10-31 21:34:48.478462000 -0700
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_status.h>
+
+#pragma pack(1)
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr_s {
+	u8         msg_class;	/*  @ref bfi_mclass_t	    */
+	u8         msg_id;		/*  msg opcode with in the class   */
+	union {
+		struct {
+			u8         rsvd;
+			u8         lpu_id;	/*  msg destination	    */
+		} h2i;
+		u16        i2htok;	/*  token in msgs to host	    */
+	} mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
+	(_mh).msg_class 		= (_mc);      \
+	(_mh).msg_id			= (_op);      \
+	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
+	(_mh).msg_class 		= (_mc);      \
+	(_mh).msg_id			= (_op);      \
+	(_mh).mtag.i2htok		= (_i2htok);      \
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE	128
+#define BFA_I2HM(_x) 			((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE	1
+#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+	BFI_SGE_DATA	= 0,	/*  data address, not last	     */
+	BFI_SGE_DATA_CPL	= 1,	/*  data addr, last in current page */
+	BFI_SGE_DATA_LAST	= 3,	/*  data address, last		     */
+	BFI_SGE_LINK	= 2,	/*  link address		     */
+	BFI_SGE_PGDLEN	= 2,	/*  cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+	struct {
+		u32        addr_lo;
+		u32        addr_hi;
+	} a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge_s {
+#ifdef __BIGENDIAN
+	u32        flags:2,
+			rsvd:2,
+			sg_len:28;
+#else
+	u32        sg_len:28,
+			rsvd:2,
+			flags:2;
+#endif
+	union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES		7
+#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN	8
+struct bfi_sgpg_s {
+	struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
+	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ		128
+#define BFI_LMSG_PL_WSZ	\
+			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
+
+struct bfi_msg_s {
+	struct bfi_mhdr_s mhdr;
+	u32	pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ		7
+struct bfi_mbmsg_s {
+	struct bfi_mhdr_s	mh;
+	u32		pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */
+	BFI_MC_DIAG		= 2,	/*  Diagnostic Msgs		    */
+	BFI_MC_FLASH		= 3,	/*  Flash message class	    */
+	BFI_MC_CEE		= 4,
+	BFI_MC_FC_PORT		= 5,	/*  FC port		   	    */
+	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */
+	BFI_MC_LL		= 7,	/*  Link Layer		 	    */
+	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */
+	BFI_MC_FCXP		= 9,	/*  FC Transport		    */
+	BFI_MC_LPS		= 10,	/*  lport fc login services	    */
+	BFI_MC_RPORT		= 11,	/*  Remote port		    */
+	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */
+	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */
+	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */
+	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */
+	BFI_MC_IOIM		= 16,	/*  IO (Initiator mode)	    */
+	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */
+	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */
+	BFI_MC_SBOOT		= 19,	/*  SAN boot services		    */
+	BFI_MC_IPFC		= 20,	/*  IP over FC Msgs		    */
+	BFI_MC_PORT		= 21,	/*  Physical port		    */
+	BFI_MC_MAX		= 32
+};
+
+#define BFI_IOC_MAX_CQS		4
+#define BFI_IOC_MAX_CQS_ASIC	8
+#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_boot.h net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_boot.h
--- net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_boot.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_boot.h	2009-10-31 21:34:48.522464000 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+/*
+ * bfi_boot.h
+ */
+
+#ifndef __BFI_BOOT_H__
+#define __BFI_BOOT_H__
+
+#define BFI_BOOT_TYPE_OFF		8
+#define BFI_BOOT_PARAM_OFF		12
+
+#define BFI_BOOT_TYPE_NORMAL 		0	/* param is device id */
+#define	BFI_BOOT_TYPE_FLASH		1
+#define	BFI_BOOT_TYPE_MEMTEST		2
+
+#define BFI_BOOT_MEMTEST_RES_ADDR   0x900
+#define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
+
+#endif
diff -ruP net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_cee.h net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_cee.h
--- net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_cee.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_cee.h	2009-10-31 21:34:48.573462000 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/**
+ *  Copyright (c) 2006-2009 Brocade Communications Systems, Inc.
+ *  All rights reserved.
+ *
+ *  bfi_dcbx.h BFI Interface (Mailbox commands and related structures)
+ * between host driver and DCBX/LLDP firmware module.
+ *
+**/
+
+#ifndef __BFI_CEE_H__
+#define __BFI_CEE_H__
+
+#include <bfi/bfi.h>
+
+#pragma pack(1)
+
+
+enum bfi_cee_h2i_msgs_e {
+	BFI_CEE_H2I_GET_CFG_REQ = 1,
+	BFI_CEE_H2I_RESET_STATS = 2,
+	BFI_CEE_H2I_GET_STATS_REQ = 3,
+};
+
+
+enum bfi_cee_i2h_msgs_e {
+	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
+	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
+	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
+};
+
+
+/* Data structures */
+
+/*
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_lldp_reset_stats_s {
+	struct bfi_mhdr_s  mh;
+};
+
+/*
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_cee_reset_stats_s {
+	struct bfi_mhdr_s  mh;
+};
+
+/*
+ * BFI_CEE_H2I_GET_CFG_REQ
+ */
+struct bfi_cee_get_req_s {
+	struct bfi_mhdr_s  mh;
+	union bfi_addr_u   dma_addr;
+};
+
+
+/*
+ * BFI_CEE_I2H_GET_CFG_RSP
+ */
+struct bfi_cee_get_rsp_s {
+	struct bfi_mhdr_s  mh;
+	u8            cmd_status;
+	u8            rsvd[3];
+};
+
+/*
+ * BFI_CEE_H2I_GET_STATS_REQ
+ */
+struct bfi_cee_stats_req_s {
+	struct bfi_mhdr_s  mh;
+	union bfi_addr_u   dma_addr;
+};
+
+
+/*
+ * BFI_CEE_I2H_GET_STATS_RSP
+ */
+struct bfi_cee_stats_rsp_s {
+	struct bfi_mhdr_s  mh;
+	u8 		   cmd_status;
+	u8 		   rsvd[3];
+};
+
+
+
+union bfi_cee_h2i_msg_u {
+	struct bfi_mhdr_s           mh;
+	struct bfi_cee_get_req_s   get_req;
+	struct bfi_cee_stats_req_s stats_req;
+};
+
+
+union bfi_cee_i2h_msg_u {
+	struct bfi_mhdr_s         mh;
+	struct bfi_cee_get_rsp_s  get_rsp;
+	struct bfi_cee_stats_rsp_s stats_rsp;
+};
+
+#pragma pack()
+
+
+#endif /* __BFI_CEE_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_ctreg.h net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_ctreg.h
--- net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_ctreg.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_ctreg.h	2009-10-31 21:34:48.581463000 -0700
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+
+#define HOSTFN0_LPU_MBOX0_0              0x00019200
+#define HOSTFN1_LPU_MBOX0_8              0x00019260
+#define LPU_HOSTFN0_MBOX0_0              0x00019280
+#define LPU_HOSTFN1_MBOX0_8              0x000192e0
+#define HOSTFN2_LPU_MBOX0_0              0x00019400
+#define HOSTFN3_LPU_MBOX0_8              0x00019460
+#define LPU_HOSTFN2_MBOX0_0              0x00019480
+#define LPU_HOSTFN3_MBOX0_8              0x000194e0
+#define HOSTFN0_INT_STATUS               0x00014000
+#define __HOSTFN0_HALT_OCCURRED          0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH      20
+#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH        16
+#define __HOSTFN0_INT_STATUS_P(_v)       ((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F           0x0000ffff
+#define HOSTFN0_INT_MSK                  0x00014004
+#define HOST_PAGE_NUM_FN0                0x00014008
+#define __HOST_PAGE_NUM_FN               0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0          0x0001400c
+#define __MSIX_ERR_INDEX_FN              0x000001ff
+#define HOSTFN1_INT_STATUS               0x00014100
+#define __HOSTFN1_HALT_OCCURRED          0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH      20
+#define __HOSTFN1_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH        16
+#define __HOSTFN1_INT_STATUS_P(_v)       ((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F           0x0000ffff
+#define HOSTFN1_INT_MSK                  0x00014104
+#define HOST_PAGE_NUM_FN1                0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1          0x0001410c
+#define APP_PLL_425_CTL_REG              0x00014204
+#define __P_425_PLL_LOCK                 0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ    0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH     17
+#define __APP_PLL_425_RESET_TIMER(_v)    ((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH       14
+#define __APP_PLL_425_CNTLMT0_1(_v)      ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH       12
+#define __APP_PLL_425_JITLMT0_1(_v)      ((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF               0x00000800
+#define __APP_PLL_425_HDIV               0x00000400
+#define __APP_PLL_425_P0_1_MK            0x00000300
+#define __APP_PLL_425_P0_1_SH            8
+#define __APP_PLL_425_P0_1(_v)           ((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK            0x000000e0
+#define __APP_PLL_425_Z0_2_SH            5
+#define __APP_PLL_425_Z0_2(_v)           ((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500         0x00000010
+#define __APP_PLL_425_ENARST             0x00000008
+#define __APP_PLL_425_BYPASS             0x00000004
+#define __APP_PLL_425_LRESETN            0x00000002
+#define __APP_PLL_425_ENABLE             0x00000001
+#define APP_PLL_312_CTL_REG              0x00014208
+#define __P_312_PLL_LOCK                 0x80000000
+#define __ENABLE_MAC_AHB_1               0x00800000
+#define __ENABLE_MAC_AHB_0               0x00400000
+#define __ENABLE_MAC_1                   0x00200000
+#define __ENABLE_MAC_0                   0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH     17
+#define __APP_PLL_312_RESET_TIMER(_v)    ((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH       14
+#define __APP_PLL_312_CNTLMT0_1(_v)      ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH       12
+#define __APP_PLL_312_JITLMT0_1(_v)      ((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF               0x00000800
+#define __APP_PLL_312_HDIV               0x00000400
+#define __APP_PLL_312_P0_1_MK            0x00000300
+#define __APP_PLL_312_P0_1_SH            8
+#define __APP_PLL_312_P0_1(_v)           ((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK            0x000000e0
+#define __APP_PLL_312_Z0_2_SH            5
+#define __APP_PLL_312_Z0_2(_v)           ((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500         0x00000010
+#define __APP_PLL_312_ENARST             0x00000008
+#define __APP_PLL_312_BYPASS             0x00000004
+#define __APP_PLL_312_LRESETN            0x00000002
+#define __APP_PLL_312_ENABLE             0x00000001
+#define MBIST_CTL_REG                    0x00014220
+#define __EDRAM_BISTR_START              0x00000004
+#define __MBIST_RESET                    0x00000002
+#define __MBIST_START                    0x00000001
+#define MBIST_STAT_REG                   0x00014224
+#define __EDRAM_BISTR_STATUS             0x00000008
+#define __EDRAM_BISTR_DONE               0x00000004
+#define __MEM_BIT_STATUS                 0x00000002
+#define __MBIST_DONE                     0x00000001
+#define HOST_SEM0_REG                    0x00014230
+#define __HOST_SEMAPHORE                 0x00000001
+#define HOST_SEM1_REG                    0x00014234
+#define HOST_SEM2_REG                    0x00014238
+#define HOST_SEM3_REG                    0x0001423c
+#define HOST_SEM0_INFO_REG               0x00014240
+#define HOST_SEM1_INFO_REG               0x00014244
+#define HOST_SEM2_INFO_REG               0x00014248
+#define HOST_SEM3_INFO_REG               0x0001424c
+#define ETH_MAC_SER_REG                  0x00014288
+#define __APP_EMS_CKBUFAMPIN             0x00000020
+#define __APP_EMS_REFCLKSEL              0x00000010
+#define __APP_EMS_CMLCKSEL               0x00000008
+#define __APP_EMS_REFCKBUFEN2            0x00000004
+#define __APP_EMS_REFCKBUFEN1            0x00000002
+#define __APP_EMS_CHANNEL_SEL            0x00000001
+#define HOSTFN2_INT_STATUS               0x00014300
+#define __HOSTFN2_HALT_OCCURRED          0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH      20
+#define __HOSTFN2_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH        16
+#define __HOSTFN2_INT_STATUS_P(_v)       ((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F           0x0000ffff
+#define HOSTFN2_INT_MSK                  0x00014304
+#define HOST_PAGE_NUM_FN2                0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2          0x0001430c
+#define HOSTFN3_INT_STATUS               0x00014400
+#define __HALT_OCCURRED                  0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH      20
+#define __HOSTFN3_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH        16
+#define __HOSTFN3_INT_STATUS_P(_v)       ((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F           0x0000ffff
+#define HOSTFN3_INT_MSK                  0x00014404
+#define HOST_PAGE_NUM_FN3                0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3          0x0001440c
+#define FNC_ID_REG                       0x00014600
+#define __FUNCTION_NUMBER                0x00000007
+#define FNC_PERS_REG                     0x00014604
+#define __F3_FUNCTION_ACTIVE             0x80000000
+#define __F3_FUNCTION_MODE               0x40000000
+#define __F3_PORT_MAP_MK                 0x30000000
+#define __F3_PORT_MAP_SH                 28
+#define __F3_PORT_MAP(_v)                ((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE                     0x08000000
+#define __F3_INTX_STATUS_MK              0x07000000
+#define __F3_INTX_STATUS_SH              24
+#define __F3_INTX_STATUS(_v)             ((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE             0x00800000
+#define __F2_FUNCTION_MODE               0x00400000
+#define __F2_PORT_MAP_MK                 0x00300000
+#define __F2_PORT_MAP_SH                 20
+#define __F2_PORT_MAP(_v)                ((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE                     0x00080000
+#define __F2_INTX_STATUS_MK              0x00070000
+#define __F2_INTX_STATUS_SH              16
+#define __F2_INTX_STATUS(_v)             ((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE             0x00008000
+#define __F1_FUNCTION_MODE               0x00004000
+#define __F1_PORT_MAP_MK                 0x00003000
+#define __F1_PORT_MAP_SH                 12
+#define __F1_PORT_MAP(_v)                ((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE                     0x00000800
+#define __F1_INTX_STATUS_MK              0x00000700
+#define __F1_INTX_STATUS_SH              8
+#define __F1_INTX_STATUS(_v)             ((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE             0x00000080
+#define __F0_FUNCTION_MODE               0x00000040
+#define __F0_PORT_MAP_MK                 0x00000030
+#define __F0_PORT_MAP_SH                 4
+#define __F0_PORT_MAP(_v)                ((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE                     0x00000008
+#define __F0_INTX_STATUS                 0x00000007
+enum {
+    __F0_INTX_STATUS_MSIX            = 0x0,
+    __F0_INTX_STATUS_INTA            = 0x1,
+    __F0_INTX_STATUS_INTB            = 0x2,
+    __F0_INTX_STATUS_INTC            = 0x3,
+    __F0_INTX_STATUS_INTD            = 0x4,
+};
+#define OP_MODE                          0x0001460c
+#define __APP_ETH_CLK_LOWSPEED           0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED       0x00000002
+#define __GLOBAL_FCOE_MODE               0x00000001
+#define HOST_SEM4_REG                    0x00014610
+#define HOST_SEM5_REG                    0x00014614
+#define HOST_SEM6_REG                    0x00014618
+#define HOST_SEM7_REG                    0x0001461c
+#define HOST_SEM4_INFO_REG               0x00014620
+#define HOST_SEM5_INFO_REG               0x00014624
+#define HOST_SEM6_INFO_REG               0x00014628
+#define HOST_SEM7_INFO_REG               0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT      0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT      0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS  0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT      0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT      0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT      0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT      0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS  0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT      0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT      0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT      0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT      0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT      0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT      0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT      0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT      0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS  0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT      0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT      0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
+#define FW_INIT_HALT_P0                  0x000191ac
+#define __FW_INIT_HALT_P                 0x00000001
+#define FW_INIT_HALT_P1                  0x000191bc
+#define CPE_PI_PTR_Q0                    0x00038000
+#define __CPE_PI_UNUSED_MK               0xffff0000
+#define __CPE_PI_UNUSED_SH               16
+#define __CPE_PI_UNUSED(_v)              ((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR                     0x0000ffff
+#define CPE_PI_PTR_Q1                    0x00038040
+#define CPE_CI_PTR_Q0                    0x00038004
+#define __CPE_CI_UNUSED_MK               0xffff0000
+#define __CPE_CI_UNUSED_SH               16
+#define __CPE_CI_UNUSED(_v)              ((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR                     0x0000ffff
+#define CPE_CI_PTR_Q1                    0x00038044
+#define CPE_DEPTH_Q0                     0x00038008
+#define __CPE_DEPTH_UNUSED_MK            0xf8000000
+#define __CPE_DEPTH_UNUSED_SH            27
+#define __CPE_DEPTH_UNUSED(_v)           ((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK          0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH          16
+#define __CPE_MSIX_VEC_INDEX(_v)         ((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH                      0x0000ffff
+#define CPE_DEPTH_Q1                     0x00038048
+#define CPE_QCTRL_Q0                     0x0003800c
+#define __CPE_CTRL_UNUSED30_MK           0xfc000000
+#define __CPE_CTRL_UNUSED30_SH           26
+#define __CPE_CTRL_UNUSED30(_v)          ((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK           0x03000000
+#define __CPE_FUNC_INT_CTRL_SH           24
+#define __CPE_FUNC_INT_CTRL(_v)          ((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+    __CPE_FUNC_INT_CTRL_DISABLE      = 0x0,
+    __CPE_FUNC_INT_CTRL_F2NF         = 0x1,
+    __CPE_FUNC_INT_CTRL_3QUART       = 0x2,
+    __CPE_FUNC_INT_CTRL_HALF         = 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK           0x00f00000
+#define __CPE_CTRL_UNUSED20_SH           20
+#define __CPE_CTRL_UNUSED20(_v)          ((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK                  0x000f0000
+#define __CPE_SCI_TH_SH                  16
+#define __CPE_SCI_TH(_v)                 ((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK           0x0000c000
+#define __CPE_CTRL_UNUSED10_SH           14
+#define __CPE_CTRL_UNUSED10(_v)          ((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING                0x00002000
+#define __CPE_CTRL_UNUSED40_MK           0x00001c00
+#define __CPE_CTRL_UNUSED40_SH           10
+#define __CPE_CTRL_UNUSED40(_v)          ((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK                  0x00000300
+#define __CPE_PCIEID_SH                  8
+#define __CPE_PCIEID(_v)                 ((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK           0x000000fe
+#define __CPE_CTRL_UNUSED00_SH           1
+#define __CPE_CTRL_UNUSED00(_v)          ((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE                      0x00000001
+#define CPE_QCTRL_Q1                     0x0003804c
+#define __CPE_CTRL_UNUSED31_MK           0xfc000000
+#define __CPE_CTRL_UNUSED31_SH           26
+#define __CPE_CTRL_UNUSED31(_v)          ((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK           0x00f00000
+#define __CPE_CTRL_UNUSED21_SH           20
+#define __CPE_CTRL_UNUSED21(_v)          ((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK           0x0000c000
+#define __CPE_CTRL_UNUSED11_SH           14
+#define __CPE_CTRL_UNUSED11(_v)          ((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK           0x00001c00
+#define __CPE_CTRL_UNUSED41_SH           10
+#define __CPE_CTRL_UNUSED41(_v)          ((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK           0x000000fe
+#define __CPE_CTRL_UNUSED01_SH           1
+#define __CPE_CTRL_UNUSED01(_v)          ((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0                    0x00038020
+#define __LATENCY_TIME_STAMP_MK          0xffff0000
+#define __LATENCY_TIME_STAMP_SH          16
+#define __LATENCY_TIME_STAMP(_v)         ((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR                     0x0000ffff
+#define RME_PI_PTR_Q1                    0x00038060
+#define RME_CI_PTR_Q0                    0x00038024
+#define __DELAY_TIME_STAMP_MK            0xffff0000
+#define __DELAY_TIME_STAMP_SH            16
+#define __DELAY_TIME_STAMP(_v)           ((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR                     0x0000ffff
+#define RME_CI_PTR_Q1                    0x00038064
+#define RME_DEPTH_Q0                     0x00038028
+#define __RME_DEPTH_UNUSED_MK            0xf8000000
+#define __RME_DEPTH_UNUSED_SH            27
+#define __RME_DEPTH_UNUSED(_v)           ((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK          0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH          16
+#define __RME_MSIX_VEC_INDEX(_v)         ((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH                      0x0000ffff
+#define RME_DEPTH_Q1                     0x00038068
+#define RME_QCTRL_Q0                     0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK       0xff000000
+#define __RME_INT_LATENCY_TIMER_SH       24
+#define __RME_INT_LATENCY_TIMER(_v)      ((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK         0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH         16
+#define __RME_INT_DELAY_TIMER(_v)        ((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE          0x00008000
+#define __RME_DLY_DELAY_DISABLE          0x00004000
+#define __RME_ACK_PENDING                0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE     0x00001000
+#define __RME_CTRL_UNUSED10_MK           0x00000c00
+#define __RME_CTRL_UNUSED10_SH           10
+#define __RME_CTRL_UNUSED10(_v)          ((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK                  0x00000300
+#define __RME_PCIEID_SH                  8
+#define __RME_PCIEID(_v)                 ((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK           0x000000fe
+#define __RME_CTRL_UNUSED00_SH           1
+#define __RME_CTRL_UNUSED00(_v)          ((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE                      0x00000001
+#define RME_QCTRL_Q1                     0x0003806c
+#define __RME_CTRL_UNUSED11_MK           0x00000c00
+#define __RME_CTRL_UNUSED11_SH           10
+#define __RME_CTRL_UNUSED11(_v)          ((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK           0x000000fe
+#define __RME_CTRL_UNUSED01_SH           1
+#define __RME_CTRL_UNUSED01(_v)          ((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG                      0x00018800
+#define __PSS_I2C_CLK_DIV_MK             0x007f0000
+#define __PSS_I2C_CLK_DIV_SH             16
+#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE             0x00001000
+#define __PSS_LMEM_RESET                 0x00000200
+#define __PSS_LMEM_INIT_EN               0x00000100
+#define __PSS_LPU1_RESET                 0x00000002
+#define __PSS_LPU0_RESET                 0x00000001
+#define HQM_QSET0_RXQ_DRBL_P0            0x00038000
+#define __RXQ0_ADD_VECTORS_P             0x80000000
+#define __RXQ0_STOP_P                    0x40000000
+#define __RXQ0_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0            0x00038080
+#define __RXQ1_ADD_VECTORS_P             0x80000000
+#define __RXQ1_STOP_P                    0x40000000
+#define __RXQ1_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1            0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1            0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0            0x00038020
+#define __TXQ0_ADD_VECTORS_P             0x80000000
+#define __TXQ0_STOP_P                    0x40000000
+#define __TXQ0_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0            0x000380a0
+#define __TXQ1_ADD_VECTORS_P             0x80000000
+#define __TXQ1_STOP_P                    0x40000000
+#define __TXQ1_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1            0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1            0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0           0x00038040
+#define __IB1_0_ACK_P                    0x80000000
+#define __IB1_0_DISABLE_P                0x40000000
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0           0x000380c0
+#define __IB1_1_ACK_P                    0x80000000
+#define __IB1_1_DISABLE_P                0x40000000
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1           0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1           0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0           0x00038060
+#define __IB2_0_ACK_P                    0x80000000
+#define __IB2_0_DISABLE_P                0x40000000
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0           0x000380e0
+#define __IB2_1_ACK_P                    0x80000000
+#define __IB2_1_DISABLE_P                0x40000000
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1           0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1           0x0003c0e0
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
+#define __EMPHPRE_AT_4G_FIX              0x00000003
+#define __SFP_TXRATE_EN_FIX              0x00000100
+#define __SFP_RXRATE_EN_FIX              0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) \
+	(HQM_QSET0_RXQ_DRBL_P0 + (__n) * (HQM_QSET1_RXQ_DRBL_P0 - \
+	HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) \
+	(HQM_QSET0_TXQ_DRBL_P0 + (__n) * (HQM_QSET1_TXQ_DRBL_P0 - \
+	HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) \
+	(HQM_QSET0_IB_DRBL_1_P0 + (__n) * (HQM_QSET1_IB_DRBL_1_P0 - \
+	HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) \
+	(HQM_QSET0_IB_DRBL_2_P0 + (__n) * (HQM_QSET1_IB_DRBL_2_P0 - \
+	HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) \
+	(HQM_QSET0_RXQ_DRBL_P1 + (__n) * (HQM_QSET1_RXQ_DRBL_P1 - \
+	HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) \
+	(HQM_QSET0_TXQ_DRBL_P1 + (__n) * (HQM_QSET1_TXQ_DRBL_P1 - \
+	HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) \
+	(HQM_QSET0_IB_DRBL_1_P1 + (__n) * (HQM_QSET1_IB_DRBL_1_P1 - \
+	HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) \
+	(HQM_QSET0_IB_DRBL_2_P1 + (__n) * (HQM_QSET1_IB_DRBL_2_P1 - \
+	HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q)  ((__q) & 0x3)
+#define RME_Q_MASK(__q)  ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+    BFA_MSIX_CPE_Q0 = 0,
+    BFA_MSIX_CPE_Q1 = 1,
+    BFA_MSIX_CPE_Q2 = 2,
+    BFA_MSIX_CPE_Q3 = 3,
+    BFA_MSIX_RME_Q0 = 4,
+    BFA_MSIX_RME_Q1 = 5,
+    BFA_MSIX_RME_Q2 = 6,
+    BFA_MSIX_RME_Q3 = 7,
+    BFA_MSIX_LPU_ERR = 8,
+    BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0                   0x00000001U
+#define __HFN_INT_CPE_Q1                   0x00000002U
+#define __HFN_INT_CPE_Q2                   0x00000004U
+#define __HFN_INT_CPE_Q3                   0x00000008U
+#define __HFN_INT_CPE_Q4                   0x00000010U
+#define __HFN_INT_CPE_Q5                   0x00000020U
+#define __HFN_INT_CPE_Q6                   0x00000040U
+#define __HFN_INT_CPE_Q7                   0x00000080U
+#define __HFN_INT_RME_Q0                   0x00000100U
+#define __HFN_INT_RME_Q1                   0x00000200U
+#define __HFN_INT_RME_Q2                   0x00000400U
+#define __HFN_INT_RME_Q3                   0x00000800U
+#define __HFN_INT_RME_Q4                   0x00001000U
+#define __HFN_INT_RME_Q5                   0x00002000U
+#define __HFN_INT_RME_Q6                   0x00004000U
+#define __HFN_INT_RME_Q7                   0x00008000U
+#define __HFN_INT_ERR_EMC                  0x00010000U
+#define __HFN_INT_ERR_LPU0                 0x00020000U
+#define __HFN_INT_ERR_LPU1                 0x00040000U
+#define __HFN_INT_ERR_PSS                  0x00080000U
+#define __HFN_INT_MBOX_LPU0                0x00100000U
+#define __HFN_INT_MBOX_LPU1                0x00200000U
+#define __HFN_INT_MBOX1_LPU0               0x00400000U
+#define __HFN_INT_MBOX1_LPU1               0x00800000U
+#define __HFN_INT_CPE_MASK                 0x000000ffU
+#define __HFN_INT_RME_MASK                 0x0000ff00U
+
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0                      0x0096
+#define LL_PGN_HQM1                      0x0097
+#define PSS_SMEM_PAGE_START	0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+
+#endif /* __BFI_CTREG_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_ioc.h net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_ioc.h
--- net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_ioc.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_ioc.h	2009-10-31 21:34:48.566465000 -0700
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFI_IOC_H__
+#define __BFI_IOC_H__
+
+#include "bfi.h"
+#include <defs/bfa_defs_ioc.h>
+
+#pragma pack(1)
+
+enum bfi_ioc_h2i_msgs {
+	BFI_IOC_H2I_ENABLE_REQ 		= 1,
+	BFI_IOC_H2I_DISABLE_REQ 	= 2,
+	BFI_IOC_H2I_GETATTR_REQ 	= 3,
+	BFI_IOC_H2I_DBG_SYNC	 	= 4,
+	BFI_IOC_H2I_DBG_DUMP	 	= 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
+	BFI_IOC_I2H_DISABLE_REPLY 	= BFA_I2HM(2),
+	BFI_IOC_I2H_GETATTR_REPLY 	= BFA_I2HM(3),
+	BFI_IOC_I2H_READY_EVENT 	= BFA_I2HM(4),
+	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req_s {
+	struct bfi_mhdr_s	mh;
+	union bfi_addr_u	attr_addr;
+};
+
+struct bfi_ioc_attr_s {
+	wwn_t           mfg_wwn;
+	mac_t		mfg_mac;
+	u16	rsvd_a;
+	char            brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	u8         pcie_gen;
+	u8         pcie_lanes_orig;
+	u8         pcie_lanes;
+	u8         rx_bbcredit;	/*  receive buffer credits */
+	u32        adapter_prop;	/*  adapter properties     */
+	u16        maxfrsize;	/*  max receive frame size */
+	char         	asic_rev;
+	u8         rsvd_b;
+	char            fw_version[BFA_VERSION_LEN];
+	char            optrom_version[BFA_VERSION_LEN];
+	struct bfa_mfg_vpd_s	vpd;
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header          */
+	u8		status;	/*  cfg reply status           */
+	u8		rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB	(0x40)
+#define BFI_IOC_SMEM_PG0_CT	(0x180)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF		(0x4b00)
+#define BFI_IOC_TRC_ENTS	256
+
+#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ	4
+struct bfi_ioc_image_hdr_s {
+	u32        signature;	/*  constant signature */
+	u32        rsvd_a;
+	u32        exec;		/*  exec vector        */
+	u32        param;		/*  parameters         */
+	u32        rsvd_b[4];
+	u32        md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ *  BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event_s {
+	struct bfi_mhdr_s  mh;			/*  common msg header */
+	u8         init_status;	/*  init event status */
+	u8         rsvd[3];
+};
+
+struct bfi_ioc_hbeat_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u32	   hb_count;	/*  current heart beat count	*/
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+	BFI_IOC_UNINIT 	 = 0,		/*  not initialized                 */
+	BFI_IOC_INITING 	 = 1,	/*  h/w is being initialized        */
+	BFI_IOC_HWINIT 	 = 2,		/*  h/w is initialized              */
+	BFI_IOC_CFG 	 = 3,		/*  IOC configuration in progress   */
+	BFI_IOC_OP 		 = 4,	/*  IOC is operational              */
+	BFI_IOC_DISABLING 	 = 5,	/*  IOC is being disabled           */
+	BFI_IOC_DISABLED 	 = 6,	/*  IOC is disabled                 */
+	BFI_IOC_CFG_DISABLED = 7,	/*  IOC is being disabled;transient */
+	BFI_IOC_HBFAIL       = 8,	/*  IOC heart-beat failure          */
+	BFI_IOC_MEMTEST      = 9,	/*  IOC is doing memtest            */
+};
+
+#define BFI_IOC_ENDIAN_SIG  0x12345678
+
+enum {
+	BFI_ADAPTER_TYPE_FC   = 0x01,		/*  FC adapters           */
+	BFI_ADAPTER_TYPE_MK   = 0x0f0000,	/*  adapter type mask     */
+	BFI_ADAPTER_TYPE_SH   = 16,	        /*  adapter type shift    */
+	BFI_ADAPTER_NPORTS_MK = 0xff00,		/*  number of ports mask  */
+	BFI_ADAPTER_NPORTS_SH = 8,	        /*  number of ports shift */
+	BFI_ADAPTER_SPEED_MK  = 0xff,		/*  adapter speed mask    */
+	BFI_ADAPTER_SPEED_SH  = 0,	        /*  adapter speed shift   */
+	BFI_ADAPTER_PROTO     = 0x100000,	/*  prototype adapaters   */
+	BFI_ADAPTER_TTV       = 0x200000,	/*  TTV debug capable     */
+	BFI_ADAPTER_UNSUPP    = 0x400000,	/*  unknown adapter type  */
+};
+
+#define BFI_ADAPTER_GETP(__prop, __adap_prop)          		\
+    (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>         \
+     BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val)         		\
+    ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type)   			\
+    ((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type)     			\
+    ((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type)  			\
+    ((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type)                     \
+    ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |     \
+			BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req_s {
+	struct bfi_mhdr_s	mh;
+	u8			ioc_class;
+	u8         	rsvd[3];
+};
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header     */
+	u8         status;		/*  enable/disable status */
+	u8         rsvd[3];
+};
+
+#define BFI_IOC_MSGSZ   8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+	struct bfi_mhdr_s 	mh;
+	struct bfi_ioc_ctrl_req_s enable_req;
+	struct bfi_ioc_ctrl_req_s disable_req;
+	struct bfi_ioc_getattr_req_s getattr_req;
+	u32       		mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+	struct bfi_mhdr_s      	mh;
+	struct bfi_ioc_rdy_event_s 	rdy_event;
+	u32       		mboxmsg[BFI_IOC_MSGSZ];
+};
+
+#pragma pack()
+
+#endif /* __BFI_IOC_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_ll.h net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_ll.h
--- net-next-2.6-orig/drivers/net/bna/include/bfi/bfi_ll.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/bfi/bfi_ll.h	2009-10-31 21:34:48.588462000 -0700
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ *	Copyright (c) 2007-2008 Brocade Communications Systems, Inc.
+ *	All rights reserved.
+ *
+ *	file bfi_if.h BNA Hardware and Firmware Interface
+ */
+#ifndef __BFI_LL_H__
+#define __BFI_LL_H__
+
+#include <bfi/bfi.h>
+#include <defs/bfa_defs_ioc.h>
+
+#pragma pack(1)
+
+/**
+ *	"enums" for all LL mailbox messages other than IOC
+ */
+enum {
+	BFI_LL_H2I_MAC_UCAST_SET_REQ = 1,
+	BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2,
+	BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3,
+
+	BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4,
+	BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5,
+	BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6,
+	BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7,
+
+	BFI_LL_H2I_PORT_ADMIN_REQ = 8,
+	BFI_LL_H2I_STATS_GET_REQ = 9,
+	BFI_LL_H2I_STATS_CLEAR_REQ = 10,
+
+	BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11,
+	BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12,
+
+	BFI_LL_H2I_TXQ_STOP_REQ = 13,
+	BFI_LL_H2I_RXQ_STOP_REQ = 14,
+
+	BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15,
+
+	BFI_LL_H2I_SET_PAUSE_REQ = 16,
+	BFI_LL_H2I_MTU_INFO_REQ = 17,
+
+	BFI_LL_H2I_RX_REQ = 18,
+};
+
+enum {
+	BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1),
+	BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2),
+	BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3),
+
+	BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4),
+	BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5),
+	BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6),
+	BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7),
+
+	BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8),
+	BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9),
+	BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10),
+
+	BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11),
+	BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12),
+
+	BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13),
+	BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14),
+
+	BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15),
+
+	BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16),
+
+	BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17),
+	BFI_LL_I2H_RX_RSP = BFA_I2HM(18),
+
+	BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19),
+	BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20),
+	BFI_LL_I2H_CEE_DOWN_AEN = BFA_I2HM(21),
+	BFI_LL_I2H_CEE_UP_AEN = BFA_I2HM(22),
+};
+
+/**
+ *        BFI_LL_H2I_MAC_UCAST_SET_REQ
+ *        BFI_LL_H2I_MAC_UCAST_ADD_REQ
+ *        BFI_LL_H2I_MAC_UCAST_DEL_REQ
+ *        BFI_LL_H2I_MAC_MCAST_ADD_REQ
+ *        BFI_LL_H2I_MAC_MCAST_DEL_REQ
+ */
+struct bfi_ll_mac_addr_req {
+	struct bfi_mhdr_s  mh;         /*  common msg header */
+	u8		rxf_id;
+	u8		rsvd1[3];
+	mac_t		mac_addr;
+	u8		rsvd2[2];
+};
+
+/**
+ *	  BFI_LL_H2I_MAC_MCAST_FILTER_REQ
+ */
+struct bfi_ll_mcast_filter_req {
+	struct bfi_mhdr_s  mh;         /*  common msg header */
+	u8		rxf_id;
+	u8		enable;
+	u8		rsvd[2];
+};
+
+/**
+ *	  BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ
+ */
+struct bfi_ll_mcast_del_all_req {
+	struct bfi_mhdr_s  mh;         /*  common msg header */
+	u8		   rxf_id;
+	u8		   rsvd[3];
+};
+
+/**
+ *	BFI_LL_H2I_TXQ_STOP_REQ
+ *	BFI_LL_H2I_RXQ_STOP_REQ
+ */
+struct bfi_ll_q_stop_req {
+	struct bfi_mhdr_s mh;		/*  common msg header */
+	u32	q_id_mask[2];	/*  bit-mask for queue ids */
+};
+
+/**
+ *    BFI_LL_I2H_STATS_GET_REQ
+ *    BFI_LL_I2H_STATS_CLEAR_REQ
+ */
+struct bfi_ll_stats_req {
+	struct bfi_mhdr_s  mh;         		/*  common msg header */
+/*  bit-mask for non-function statistics */
+	u16	stats_mask;
+	u8		rsvd[2];
+	u32	rxf_id_mask[2];		 /*  bit-mask for RxF Statistics */
+	u32	txf_id_mask[2];		 /*  bit-mask for TxF Statistics */
+/*  where statistics are returned */
+	union bfi_addr_u  host_buffer;
+};
+
+
+#define BFI_LL_STATS_MAC	(1 << 0)	/*  MAC Statistics */
+#define BFI_LL_STATS_BPC	(1 << 1)	/*  Pause Stats from BPC */
+#define BFI_LL_STATS_RAD	(1 << 2)	/*  Rx Admission Statistics */
+#define BFI_LL_STATS_RX_FC	(1 << 3)	/*  Rx FC Stats from RxA */
+#define BFI_LL_STATS_TX_FC	(1 << 4)	/*  Tx FC Stats from TxA */
+
+#define BFI_LL_STATS_ALL	0x1f
+
+
+
+struct bfi_ll_port_admin_req {
+	struct bfi_mhdr_s  mh;         		/*  common msg header */
+	u8		 up;
+	u8		 rsvd[3];
+};
+
+/**
+ *      BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ
+ *      BFI_LL_H2I_RXF_DEFAULT_SET_REQ
+ */
+struct bfi_ll_rxf_req {
+	struct bfi_mhdr_s  mh;         /*  common msg header */
+	u8		rxf_id;
+	u8		enable;
+	u8		rsvd[2];
+};
+
+/**
+ *      BFI_LL_H2I_RX_REQ
+ */
+struct bfi_ll_rxf_multi_req {
+	struct bfi_mhdr_s  mh;         /*  common msg header */
+	u32	rxf_id_mask[2];
+	u8		enable;
+	u8		rsvd[3];
+};
+
+/**
+ *      BFI_LL_H2I_DIAG_LOOPBACK
+ */
+struct bfi_ll_diag_lb_req{
+		struct bfi_mhdr_s		mh;		/* 4 bytes */
+/* =1 : enable, =0 : disable */
+		u8					enable;
+/* cable or Serdes */
+		u8					mode;
+		u8					rsvd[2];
+};
+
+
+enum {
+	BFI_LL_DIAG_LB_OPMODE_EXT = 0,
+	BFI_LL_DIAG_LB_OPMODE_CBL = 1,
+};
+
+/**
+ *	BFI_LL_H2I_SET_PAUSE_REQ
+ */
+struct bfi_ll_set_pause_req {
+	struct bfi_mhdr_s mh;
+	u8		tx_pause; /* 1 = enable, 0 =  disable */
+	u8		rx_pause; /* 1 = enable, 0 =  disable */
+	u8		rsvd[2];
+};
+
+/**
+ *	BFI_LL_H2I_MTU_INFO_REQ
+ */
+struct bfi_ll_mtu_info_req {
+	struct bfi_mhdr_s mh;
+	u16	mtu;
+	u8		rsvd[2];
+};
+
+/**
+ *	  Response header format used by all responses
+ *	  For both responses and asynchronous notifications
+ */
+struct bfi_ll_rsp {
+	struct bfi_mhdr_s  mh;         		/*  common msg header */
+	u8 	 error;
+	u8		 rsvd[3];
+};
+
+/**
+ *	BFI_LL_I2H_LINK_DOWN_AEN
+ *	BFI_LL_I2H_LINK_UP_AEN
+ *	BFI_LL_I2H_CEE_DOWN_AEN
+ *	BFI_LL_I2H_CEE_UP_AEN
+ */
+struct bfi_ll_aen {
+	struct bfi_mhdr_s  mh;          /*  common msg header */
+	u32           reason;
+	u8            prio_map;    /*  LL priority bit-map */
+	u8            rsvd[3];
+};
+
+/**
+ * 	The following error codes can be returned
+ *	by the mbox commands
+ */
+enum {
+	BFI_LL_CMD_OK 		= 0,
+	BFI_LL_CMD_FAIL 	= 1,
+	BFI_LL_CMD_DUP_ENTRY	= 2,	/*  Duplicate entry in CAM */
+	BFI_LL_CMD_CAM_FULL	= 3,	/*  CAM is full */
+	BFI_LL_CMD_NOT_OWNER	= 4,   	/*  Not permitted, b'cos not owner */
+	BFI_LL_CMD_NOT_EXEC	= 5,   	/*  Was not sent to f/w at all */
+};
+
+/* Statistics */
+#define BFI_LL_TXF_ID_MAX  	64
+#define BFI_LL_RXF_ID_MAX  	64
+
+/* TxF Frame Statistics */
+struct bfi_ll_stats_txf {
+	u64 ucast_octets;
+	u64 ucast;
+	u64 ucast_vlan;
+
+	u64 mcast_octets;
+	u64 mcast;
+	u64 mcast_vlan;
+
+	u64 bcast_octets;
+	u64 bcast;
+	u64 bcast_vlan;
+
+	u64 errors;
+	u64 filter_vlan;      /* frames filtered due to VLAN */
+	u64 filter_mac_sa;    /* frames filtered due to SA check */
+};
+
+
+/* RxF Frame Statistics */
+struct bfi_ll_stats_rxf {
+	u64 ucast_octets;
+	u64 ucast;
+	u64 ucast_vlan;
+
+	u64 mcast_octets;
+	u64 mcast;
+	u64 mcast_vlan;
+
+	u64 bcast_octets;
+	u64 bcast;
+	u64 bcast_vlan;
+	u64 frame_drops;
+};
+
+
+/* FC Tx Frame Statistics */
+struct bfi_ll_stats_fc_tx {
+	u64 txf_ucast_octets;
+	u64 txf_ucast;
+	u64 txf_ucast_vlan;
+
+	u64 txf_mcast_octets;
+	u64 txf_mcast;
+	u64 txf_mcast_vlan;
+
+	u64 txf_bcast_octets;
+	u64 txf_bcast;
+	u64 txf_bcast_vlan;
+
+	u64 txf_parity_errors;
+	u64 txf_timeout;
+	u64 txf_fid_parity_errors;
+};
+
+
+/* FC Rx Frame Statistics */
+struct bfi_ll_stats_fc_rx {
+	u64 rxf_ucast_octets;
+	u64 rxf_ucast;
+	u64 rxf_ucast_vlan;
+
+	u64 rxf_mcast_octets;
+	u64 rxf_mcast;
+	u64 rxf_mcast_vlan;
+
+	u64 rxf_bcast_octets;
+	u64 rxf_bcast;
+	u64 rxf_bcast_vlan;
+};
+
+
+/* RAD Frame Statistics */
+struct bfi_ll_stats_rad {
+	u64 rx_frames;
+	u64 rx_octets;
+	u64 rx_vlan_frames;
+
+	u64 rx_ucast;
+	u64 rx_ucast_octets;
+	u64 rx_ucast_vlan;
+
+	u64 rx_mcast;
+	u64 rx_mcast_octets;
+	u64 rx_mcast_vlan;
+
+	u64 rx_bcast;
+	u64 rx_bcast_octets;
+	u64 rx_bcast_vlan;
+
+	u64 rx_drops;
+};
+
+
+/* BPC Tx Registers */
+struct bfi_ll_stats_bpc {
+    /* transmit stats */
+	u64 tx_pause[8];
+	u64 tx_zero_pause[8]; /*  Pause cancellation */
+	u64 tx_first_pause[8];/*  Pause initiation rather than retention*/
+
+	/* receive stats */
+	u64 rx_pause[8];
+	u64 rx_zero_pause[8]; /*  Pause cancellation */
+	u64 rx_first_pause[8];/*  Pause initiation rather than retention*/
+};
+
+
+/* MAC Rx Statistics */
+struct bfi_ll_stats_mac {
+	u64 frame_64;          /* both rx and tx counter */
+	u64 frame_65_127;      /* both rx and tx counter */
+	u64 frame_128_255;     /* both rx and tx counter */
+	u64 frame_256_511;     /* both rx and tx counter */
+	u64 frame_512_1023;    /* both rx and tx counter */
+	u64 frame_1024_1518;   /* both rx and tx counter */
+	u64 frame_1519_1522;   /* both rx and tx counter */
+
+	/* receive stats */
+	u64 rx_bytes;
+	u64 rx_packets;
+	u64 rx_fcs_error;
+	u64 rx_multicast;
+	u64 rx_broadcast;
+	u64 rx_control_frames;
+	u64 rx_pause;
+	u64 rx_unknown_opcode;
+	u64 rx_alignment_error;
+	u64 rx_frame_length_error;
+	u64 rx_code_error;
+	u64 rx_carrier_sense_error;
+	u64 rx_undersize;
+	u64 rx_oversize;
+	u64 rx_fragments;
+	u64 rx_jabber;
+	u64 rx_drop;
+
+	/* transmit stats */
+	u64 tx_bytes;
+	u64 tx_packets;
+	u64 tx_multicast;
+	u64 tx_broadcast;
+	u64 tx_pause;
+	u64 tx_deferral;
+	u64 tx_excessive_deferral;
+	u64 tx_single_collision;
+	u64 tx_muliple_collision;
+	u64 tx_late_collision;
+	u64 tx_excessive_collision;
+	u64 tx_total_collision;
+	u64 tx_pause_honored;
+	u64 tx_drop;
+	u64 tx_jabber;
+	u64 tx_fcs_error;
+	u64 tx_control_frame;
+	u64 tx_oversize;
+	u64 tx_undersize;
+	u64 tx_fragments;
+};
+
+
+/* Complete statistics */
+struct bfi_ll_stats {
+	struct bfi_ll_stats_mac		mac_stats;
+	struct bfi_ll_stats_bpc		bpc_stats;
+	struct bfi_ll_stats_rad		rad_stats;
+	struct bfi_ll_stats_fc_rx	fc_rx_stats;
+	struct bfi_ll_stats_fc_tx	fc_tx_stats;
+	struct bfi_ll_stats_rxf	rxf_stats[BFI_LL_RXF_ID_MAX];
+	struct bfi_ll_stats_txf	txf_stats[BFI_LL_TXF_ID_MAX];
+};
+
+#pragma pack()
+
+#endif  /* __BFI_LL_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cee/bfa_cee.h net-next-2.6-mod/drivers/net/bna/include/cee/bfa_cee.h
--- net-next-2.6-orig/drivers/net/bna/include/cee/bfa_cee.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cee/bfa_cee.h	2009-10-31 21:34:48.638466000 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFA_CEE_H__
+#define __BFA_CEE_H__
+
+#include <defs/bfa_defs_cee.h>
+#include <bfa_ioc.h>
+
+typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_cee_cbfn_s {
+	bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
+	void *get_attr_cbarg;
+	bfa_cee_get_stats_cbfn_t   get_stats_cbfn;
+	void *get_stats_cbarg;
+	bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
+	void *reset_stats_cbarg;
+};
+
+struct bfa_cee_s {
+	void *dev;
+	bfa_boolean_t get_attr_pending;
+	bfa_boolean_t get_stats_pending;
+	bfa_boolean_t reset_stats_pending;
+	bfa_status_t get_attr_status;
+	bfa_status_t get_stats_status;
+	bfa_status_t reset_stats_status;
+	struct bfa_cee_cbfn_s cbfn;
+	struct bfa_ioc_hbfail_notify_s hbfail;
+	struct bfa_trc_mod_s *trcmod;
+	struct bfa_log_mod_s *logmod;
+	struct bfa_cee_attr_s *attr;
+	struct bfa_cee_stats_s *stats;
+	struct bfa_dma_s attr_dma;
+	struct bfa_dma_s stats_dma;
+	struct bfa_ioc_s *ioc;
+	struct bfa_mbox_cmd_s get_cfg_mb;
+	struct bfa_mbox_cmd_s get_stats_mb;
+	struct bfa_mbox_cmd_s reset_stats_mb;
+};
+
+u32 bfa_cee_meminfo(void);
+void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva,
+			 u64 dma_pa);
+void bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
+			struct bfa_trc_mod_s *trcmod,
+			struct bfa_log_mod_s *logmod);
+void bfa_cee_detach(struct bfa_cee_s *cee);
+bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee,
+			 struct bfa_cee_attr_s *attr,
+			bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee,
+			struct bfa_cee_stats_s *stats,
+			bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee,
+			bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
+#endif /* __BFA_CEE_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cna/pstats/ethport_defs.h net-next-2.6-mod/drivers/net/bna/include/cna/pstats/ethport_defs.h
--- net-next-2.6-orig/drivers/net/bna/include/cna/pstats/ethport_defs.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cna/pstats/ethport_defs.h	2009-10-31 21:34:48.658462000 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __ETHPORT_DEFS_H__
+#define __ETHPORT_DEFS_H__
+
+struct bnad_drv_stats {
+	u64 netif_queue_stop;
+	u64 netif_queue_wakeup;
+	u64 tso4;
+	u64 tso6;
+	u64 tso_err;
+	u64 tcpcsum_offload;
+	u64 udpcsum_offload;
+	u64 csum_help;
+	u64 csum_help_err;
+
+	u64 hw_stats_updates;
+	u64 netif_rx_schedule;
+	u64 netif_rx_complete;
+	u64 netif_rx_dropped;
+};
+#endif
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cna/pstats/phyport_defs.h net-next-2.6-mod/drivers/net/bna/include/cna/pstats/phyport_defs.h
--- net-next-2.6-orig/drivers/net/bna/include/cna/pstats/phyport_defs.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cna/pstats/phyport_defs.h	2009-10-31 21:34:48.665462000 -0700
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __PHYPORT_DEFS_H__
+#define __PHYPORT_DEFS_H__
+
+#define BNA_TXF_ID_MAX  	64
+#define BNA_RXF_ID_MAX  	64
+
+/*
+ * Statistics
+ */
+
+/*
+ * TxF Frame Statistics
+ */
+struct bna_stats_txf {
+	u64        ucast_octets;
+	u64        ucast;
+	u64        ucast_vlan;
+
+	u64        mcast_octets;
+	u64        mcast;
+	u64        mcast_vlan;
+
+	u64        bcast_octets;
+	u64        bcast;
+	u64        bcast_vlan;
+
+	u64        errors;
+	u64        filter_vlan;	/* frames filtered due to VLAN */
+	u64        filter_mac_sa;	/* frames filtered due to SA check */
+};
+
+/*
+ * RxF Frame Statistics
+ */
+struct bna_stats_rxf {
+	u64        ucast_octets;
+	u64        ucast;
+	u64        ucast_vlan;
+
+	u64        mcast_octets;
+	u64        mcast;
+	u64        mcast_vlan;
+
+	u64        bcast_octets;
+	u64        bcast;
+	u64        bcast_vlan;
+	u64        frame_drops;
+};
+
+/*
+ * FC Tx Frame Statistics
+ */
+struct bna_stats_fc_tx {
+	u64        txf_ucast_octets;
+	u64        txf_ucast;
+	u64        txf_ucast_vlan;
+
+	u64        txf_mcast_octets;
+	u64        txf_mcast;
+	u64        txf_mcast_vlan;
+
+	u64        txf_bcast_octets;
+	u64        txf_bcast;
+	u64        txf_bcast_vlan;
+
+	u64        txf_parity_errors;
+	u64        txf_timeout;
+	u64        txf_fid_parity_errors;
+};
+
+/*
+ * FC Rx Frame Statistics
+ */
+struct bna_stats_fc_rx {
+	u64        rxf_ucast_octets;
+	u64        rxf_ucast;
+	u64        rxf_ucast_vlan;
+
+	u64        rxf_mcast_octets;
+	u64        rxf_mcast;
+	u64        rxf_mcast_vlan;
+
+	u64        rxf_bcast_octets;
+	u64        rxf_bcast;
+	u64        rxf_bcast_vlan;
+};
+
+/*
+ * RAD Frame Statistics
+ */
+struct cna_stats_rad {
+	u64        rx_frames;
+	u64        rx_octets;
+	u64        rx_vlan_frames;
+
+	u64        rx_ucast;
+	u64        rx_ucast_octets;
+	u64        rx_ucast_vlan;
+
+	u64        rx_mcast;
+	u64        rx_mcast_octets;
+	u64        rx_mcast_vlan;
+
+	u64        rx_bcast;
+	u64        rx_bcast_octets;
+	u64        rx_bcast_vlan;
+
+	u64        rx_drops;
+};
+
+/*
+ * BPC Tx Registers
+ */
+struct cna_stats_bpc_tx {
+	u64        tx_pause[8];
+	u64        tx_zero_pause[8];	/*  Pause cancellation */
+	u64        tx_first_pause[8];	/*  Pause initiation rather
+						 *than retention */
+};
+
+/*
+ * BPC Rx Registers
+ */
+struct cna_stats_bpc_rx {
+	u64        rx_pause[8];
+	u64        rx_zero_pause[8];	/*  Pause cancellation */
+	u64        rx_first_pause[8];	/*  Pause initiation rather
+						 *than retention */
+};
+
+/*
+ * MAC Rx Statistics
+ */
+struct cna_stats_mac_rx {
+	u64        frame_64;	/* both rx and tx counter */
+	u64        frame_65_127;	/* both rx and tx counter */
+	u64        frame_128_255;	/* both rx and tx counter */
+	u64        frame_256_511;	/* both rx and tx counter */
+	u64        frame_512_1023;	/* both rx and tx counter */
+	u64        frame_1024_1518;	/* both rx and tx counter */
+	u64        frame_1518_1522;	/* both rx and tx counter */
+	u64        rx_bytes;
+	u64        rx_packets;
+	u64        rx_fcs_error;
+	u64        rx_multicast;
+	u64        rx_broadcast;
+	u64        rx_control_frames;
+	u64        rx_pause;
+	u64        rx_unknown_opcode;
+	u64        rx_alignment_error;
+	u64        rx_frame_length_error;
+	u64        rx_code_error;
+	u64        rx_carrier_sense_error;
+	u64        rx_undersize;
+	u64        rx_oversize;
+	u64        rx_fragments;
+	u64        rx_jabber;
+	u64        rx_drop;
+};
+
+/*
+ * MAC Tx Statistics
+ */
+struct cna_stats_mac_tx {
+	u64        tx_bytes;
+	u64        tx_packets;
+	u64        tx_multicast;
+	u64        tx_broadcast;
+	u64        tx_pause;
+	u64        tx_deferral;
+	u64        tx_excessive_deferral;
+	u64        tx_single_collision;
+	u64        tx_muliple_collision;
+	u64        tx_late_collision;
+	u64        tx_excessive_collision;
+	u64        tx_total_collision;
+	u64        tx_pause_honored;
+	u64        tx_drop;
+	u64        tx_jabber;
+	u64        tx_fcs_error;
+	u64        tx_control_frame;
+	u64        tx_oversize;
+	u64        tx_undersize;
+	u64        tx_fragments;
+};
+
+/*
+ * Complete statistics
+ */
+struct bna_stats {
+	struct cna_stats_mac_rx mac_rx_stats;
+	struct cna_stats_bpc_rx bpc_rx_stats;
+	struct cna_stats_rad rad_stats;
+	struct bna_stats_fc_rx fc_rx_stats;
+	struct cna_stats_mac_tx mac_tx_stats;
+	struct cna_stats_bpc_tx bpc_tx_stats;
+	struct bna_stats_fc_tx fc_tx_stats;
+	struct bna_stats_rxf rxf_stats[BNA_TXF_ID_MAX];
+	struct bna_stats_txf txf_stats[BNA_RXF_ID_MAX];
+};
+
+#endif
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cs/bfa_debug.h net-next-2.6-mod/drivers/net/bna/include/cs/bfa_debug.h
--- net-next-2.6-orig/drivers/net/bna/include/cs/bfa_debug.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cs/bfa_debug.h	2009-10-31 21:34:48.699466000 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ *  bfa_debug.h BFA debug interfaces
+ */
+
+#ifndef __BFA_DEBUG_H__
+#define __BFA_DEBUG_H__
+
+#define bfa_assert(__cond)	do {					\
+	if (!(__cond)) 							\
+		bfa_panic(__LINE__, __FILE__, #__cond);      \
+} while (0)
+
+#define bfa_sm_fault(__mod, __event)	do {				\
+	bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event);      \
+} while (0)
+
+#ifndef BFA_PERF_BUILD
+#define bfa_assert_fp(__cond)	bfa_assert(__cond)
+#else
+#define bfa_assert_fp(__cond)
+#endif
+
+struct bfa_log_mod_s;
+void bfa_panic(int line, char *file, char *panicstr);
+void bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event);
+
+#endif /* __BFA_DEBUG_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cs/bfa_q.h net-next-2.6-mod/drivers/net/bna/include/cs/bfa_q.h
--- net-next-2.6-orig/drivers/net/bna/include/cs/bfa_q.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cs/bfa_q.h	2009-10-31 21:34:48.677462000 -0700
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ *  bfa_q.h Circular queue definitions.
+ */
+
+#ifndef __BFA_Q_H__
+#define __BFA_Q_H__
+
+#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
+#define bfa_q_next(_qe)	(((struct list_head *) (_qe))->next)
+#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
+
+/*
+ * bfa_q_qe_init - to initialize a queue element
+ */
+#define bfa_q_qe_init(_qe) {						\
+	bfa_q_next(_qe) = (struct list_head *) NULL;			\
+	bfa_q_prev(_qe) = (struct list_head *) NULL;			\
+}
+
+/*
+ * bfa_q_deq - dequeue an element from head of the queue
+ */
+#define bfa_q_deq(_q, _qe) {						\
+	if (!list_empty(_q)) {					\
+		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
+		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
+						(struct list_head *) (_q); \
+		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
+		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
+	} else {							\
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+	}								\
+}
+
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) {					    \
+	if (!list_empty(_q)) {					            \
+		*((struct list_head **) (_qe)) = bfa_q_prev(_q);	    \
+		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = 	    \
+						(struct list_head *) (_q);  \
+		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);    \
+		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		    \
+	} else {							    \
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+	}								    \
+}
+
+/*
+ * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
+ * consistent across modules)
+ */
+#ifndef BFA_PERF_BUILD
+#define BFA_Q_DBG_INIT(_qe)	bfa_q_qe_init(_qe)
+#else
+#define BFA_Q_DBG_INIT(_qe)
+#endif
+
+#define bfa_q_is_on_q(_q, _qe)		\
+	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
+extern int bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe);
+
+#endif
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cs/bfa_sm.h net-next-2.6-mod/drivers/net/bna/include/cs/bfa_sm.h
--- net-next-2.6-orig/drivers/net/bna/include/cs/bfa_sm.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cs/bfa_sm.h	2009-10-31 21:34:48.684462000 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ *  bfasm.h State machine defines
+ */
+
+#ifndef __BFA_SM_H__
+#define __BFA_SM_H__
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
+#define bfa_sm_get_state(_sm)		((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table_s {
+	bfa_sm_t	sm;	/*  state machine function	*/
+	int		state;	/*  state machine encoding	*/
+	char		*name;	/*  state name for display	*/
+};
+#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
+
+int bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm);
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event);      \
+	static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do {	\
+	(_fsm)->fsm = (bfa_fsm_t)(_state);      \
+	_state ## _entry(_fsm);      \
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event)	\
+	((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_cmp_state(_fsm, _state)		\
+	((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+#endif
diff -ruP net-next-2.6-orig/drivers/net/bna/include/cs/bfa_trc.h net-next-2.6-mod/drivers/net/bna/include/cs/bfa_trc.h
--- net-next-2.6-orig/drivers/net/bna/include/cs/bfa_trc.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/cs/bfa_trc.h	2009-10-31 21:34:48.693461000 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_TRC_H__
+#define __BFA_TRC_H__
+
+#ifndef BFA_TRC_MAX
+#define BFA_TRC_MAX	(4 * 1024)
+#endif
+
+struct bfa_trc_s {
+#ifdef __BIGENDIAN
+	u16	fileno;
+	u16	line;
+#else
+	u16	line;
+	u16	fileno;
+#endif
+	u32	timestamp;
+	union {
+		struct {
+			u32	rsvd;
+			u32	u32;
+		} u32;
+		u64	u64;
+	} data;
+};
+
+struct bfa_trc_mod_s {
+	u32	head;
+	u32	tail;
+	u32	ntrc;
+	u32	stopped;
+	u32	ticks;
+	u32	rsvd[3];
+	struct bfa_trc_s trc[BFA_TRC_MAX];
+};
+
+static inline void
+bfa_trc_init(struct bfa_trc_mod_s *trcm)
+{
+	trcm->head = trcm->tail = trcm->stopped = 0;
+	trcm->ntrc = BFA_TRC_MAX;
+}
+
+#endif /* __BFA_TRC_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_adapter.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_adapter.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_adapter.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_adapter.h	2009-10-31 21:34:48.712462000 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_DEFS_ADAPTER_H__
+#define __BFA_DEFS_ADAPTER_H__
+
+#include <protocol/types.h>
+#include <defs/bfa_defs_version.h>
+#include <defs/bfa_defs_mfg.h>
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+					/*
+					 *!< adapter serial num length
+					 */
+	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*  model name length */
+	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*  model description length */
+	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */
+	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */
+	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*  adapter os type length */
+};
+
+struct bfa_adapter_attr_s {
+	char            manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+	char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	u32	rsvd1;
+	char            model[BFA_ADAPTER_MODEL_NAME_LEN];
+	char            model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+	wwn_t           pwwn;
+	char            node_symname[FC_SYMNAME_MAX];
+	char            hw_ver[BFA_VERSION_LEN];
+	char            fw_ver[BFA_VERSION_LEN];
+	char            optrom_ver[BFA_VERSION_LEN];
+	char            os_type[BFA_ADAPTER_OS_TYPE_LEN];
+	struct bfa_mfg_vpd_s	vpd;
+	struct mac_s	mac;
+
+	u8		nports;
+	u8		max_speed;
+	u8		prototype;
+	char	        asic_rev;
+
+	u8         pcie_gen;
+	u8         pcie_lanes_orig;
+	u8         pcie_lanes;
+	u8	        cna_capable;
+};
+
+/**
+ * BFA adapter level events
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_PORT_AEN_ADD:        [in]: None     [out]: serial_num, pwwn, nports
+ * BFA_PORT_AEN_REMOVE:     [in]: pwwn     [out]: serial_num, pwwn, nports
+ */
+enum bfa_adapter_aen_event {
+	BFA_ADAPTER_AEN_ADD 	= 1,	/*  New Adapter found event */
+	BFA_ADAPTER_AEN_REMOVE 	= 2,	/*  Adapter removed event */
+};
+
+struct bfa_adapter_aen_data_s {
+	char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	u32        nports;	/*  Number of NPorts */
+	wwn_t           pwwn;	/*  WWN of one of its physical port */
+};
+
+#endif /* __BFA_DEFS_ADAPTER_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_cee.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_cee.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_cee.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_cee.h	2009-10-31 21:34:48.739466000 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ *  bfa_defs_cee.h Interface declarations between host based
+ *	BFAL and DCBX/LLDP module in Firmware
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_DEFS_CEE_H__
+#define __BFA_DEFS_CEE_H__
+
+#include <defs/bfa_defs_types.h>
+#include <protocol/types.h>
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
+
+
+/* FIXME: this is coming from the protocol spec. Can the host & apps share the
+   protocol .h files ?
+ */
+#define BFA_CEE_LLDP_SYS_CAP_OTHER       0x0001
+#define BFA_CEE_LLDP_SYS_CAP_REPEATER    0x0002
+#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE  0x0004
+#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP     0x0008
+#define BFA_CEE_LLDP_SYS_CAP_ROUTER      0x0010
+#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 	 0x0020
+#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD   0x0040
+#define BFA_CEE_LLDP_SYS_CAP_STATION     0x0080
+#define BFA_CEE_LLDP_SYS_CAP_CVLAN	     0x0100
+#define BFA_CEE_LLDP_SYS_CAP_SVLAN 	     0x0200
+#define BFA_CEE_LLDP_SYS_CAP_TPMR		 0x0400
+
+
+/* LLDP string type */
+struct bfa_cee_lldp_str_s {
+	u8 sub_type;
+	u8 len;
+	u8 rsvd[2];
+	u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+
+/* LLDP paramters */
+struct bfa_cee_lldp_cfg_s {
+	struct bfa_cee_lldp_str_s chassis_id;
+	struct bfa_cee_lldp_str_s port_id;
+	struct bfa_cee_lldp_str_s port_desc;
+	struct bfa_cee_lldp_str_s sys_name;
+	struct bfa_cee_lldp_str_s sys_desc;
+	struct bfa_cee_lldp_str_s mgmt_addr;
+	u16    time_to_interval;
+	u16    enabled_system_cap;
+};
+
+enum bfa_cee_dcbx_version_e {
+	DCBX_PROTOCOL_PRECEE = 1,
+	DCBX_PROTOCOL_CEE    = 2,
+};
+
+enum bfa_cee_lls_e {
+	CEE_LLS_DOWN_NO_TLV = 0, /* LLS is down because the TLV not sent by
+				  * the peer */
+	CEE_LLS_DOWN        = 1, /* LLS is down as advertised by the peer */
+	CEE_LLS_UP          = 2,
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg_s {
+	u8 pgid[8];
+	u8 pg_percentage[8];
+	u8 pfc_enabled;          /* bitmap of priorties with PFC enabled */
+	u8 fcoe_user_priority;   /* bitmap of priorities used for FcoE
+				       * traffic */
+	u8 dcbx_version;	/* operating version:CEE or preCEE */
+	u8 lls_fcoe;	/* FCoE Logical Link Status */
+	u8 lls_lan;	/* LAN Logical Link Status */
+	u8 rsvd[3];
+};
+
+/* CEE status */
+/* Making this to tri-state for the benefit of port list command */
+enum bfa_cee_status_e {
+    CEE_PHY_DOWN = 0,
+    CEE_PHY_UP = 1,
+    CEE_UP = 2,
+};
+
+/* CEE Query */
+struct bfa_cee_attr_s {
+	u8                   cee_status;
+	u8                   error_reason;
+	struct bfa_cee_lldp_cfg_s lldp_remote;
+	struct bfa_cee_dcbx_cfg_s dcbx_remote;
+	mac_t src_mac;
+	u8 link_speed;
+	u8 filler[3];
+};
+
+
+
+
+/* LLDP/DCBX/CEE Statistics */
+
+struct bfa_cee_lldp_stats_s {
+	u32 frames_transmitted;
+	u32 frames_aged_out;
+	u32 frames_discarded;
+	u32 frames_in_error;
+	u32 frames_rcvd;
+	u32 tlvs_discarded;
+	u32 tlvs_unrecognized;
+};
+
+struct bfa_cee_dcbx_stats_s {
+	u32 subtlvs_unrecognized;
+	u32 negotiation_failed;
+	u32 remote_cfg_changed;
+	u32 tlvs_received;
+	u32 tlvs_invalid;
+	u32 seqno;
+	u32 ackno;
+	u32 recvd_seqno;
+	u32 recvd_ackno;
+};
+
+struct bfa_cee_cfg_stats_s {
+	u32 cee_status_down;
+	u32 cee_status_up;
+	u32 cee_hw_cfg_changed;
+	u32 recvd_invalid_cfg;
+};
+
+
+struct bfa_cee_stats_s {
+	struct bfa_cee_lldp_stats_s lldp_stats;
+	struct bfa_cee_dcbx_stats_s dcbx_stats;
+	struct bfa_cee_cfg_stats_s  cfg_stats;
+};
+
+#pragma pack()
+
+
+#endif	/* __BFA_DEFS_CEE_H__ */
+
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_ioc.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_ioc.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_ioc.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_ioc.h	2009-10-31 21:34:48.746463000 -0700
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFA_DEFS_IOC_H__
+#define __BFA_DEFS_IOC_H__
+
+#include <protocol/types.h>
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_version.h>
+#include <defs/bfa_defs_adapter.h>
+
+enum {
+	BFA_IOC_DRIVER_LEN	= 16,
+	BFA_IOC_CHIP_REV_LEN 	= 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr_s {
+	char            driver[BFA_IOC_DRIVER_LEN];	/*  driver name */
+	char            driver_ver[BFA_VERSION_LEN];	/*  driver version */
+	char            fw_ver[BFA_VERSION_LEN];	/*  firmware version*/
+	char            bios_ver[BFA_VERSION_LEN];	/*  bios version */
+	char            efi_ver[BFA_VERSION_LEN];	/*  EFI version */
+	char            ob_ver[BFA_VERSION_LEN];	/*  openboot version*/
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr_s {
+	u16        vendor_id;	/*  PCI vendor ID */
+	u16        device_id;	/*  PCI device ID */
+	u16        ssid;		/*  subsystem ID */
+	u16        ssvid;		/*  subsystem vendor ID */
+	u32        pcifn;		/*  PCI device function */
+	u32        rsvd;		/* padding */
+	u8         chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*  chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+	BFA_IOC_RESET       = 1,  /*  IOC is in reset state */
+	BFA_IOC_SEMWAIT     = 2,  /*  Waiting for IOC hardware semaphore */
+	BFA_IOC_HWINIT 	    = 3,  /*  IOC hardware is being initialized */
+	BFA_IOC_GETATTR     = 4,  /*  IOC is being configured */
+	BFA_IOC_OPERATIONAL = 5,  /*  IOC is operational */
+	BFA_IOC_INITFAIL    = 6,  /*  IOC hardware failure */
+	BFA_IOC_HBFAIL      = 7,  /*  IOC heart-beat failure */
+	BFA_IOC_DISABLING   = 8,  /*  IOC is being disabled */
+	BFA_IOC_DISABLED    = 9,  /*  IOC is disabled */
+	BFA_IOC_FWMISMATCH  = 10, /*  IOC firmware different from drivers */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats_s {
+	u32        hb_count;
+	u32        cfg_reqs;
+	u32        enable_reqs;
+	u32        disable_reqs;
+	u32        stats_reqs;
+	u32        clrstats_reqs;
+	u32        unknown_reqs;
+	u32        ic_reqs;		/*  interrupt coalesce reqs */
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats_s {
+	u32	ioc_isrs;
+	u32	ioc_enables;
+	u32	ioc_disables;
+	u32	ioc_hbfails;
+	u32	ioc_boots;
+	u32	stats_tmos;
+	u32        hb_count;
+	u32        disable_reqs;
+	u32        enable_reqs;
+	u32        disable_replies;
+	u32        enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats_s {
+	struct bfa_ioc_drv_stats_s	drv_stats; /*  driver IOC stats */
+	struct bfa_fw_ioc_stats_s 	fw_stats;  /*  firmware IOC stats */
+};
+
+
+enum bfa_ioc_type_e {
+	BFA_IOC_TYPE_FC	  = 1,
+	BFA_IOC_TYPE_FCoE = 2,
+	BFA_IOC_TYPE_LL	  = 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr_s {
+	enum bfa_ioc_type_e		ioc_type;
+	enum bfa_ioc_state 		state;		/*  IOC state      */
+	struct bfa_adapter_attr_s	adapter_attr;	/*  HBA attributes */
+	struct bfa_ioc_driver_attr_s 	driver_attr;	/*  driver attr    */
+	struct bfa_ioc_pci_attr_s	pci_attr;
+	u8				port_id;	/*  port number    */
+};
+
+/**
+ * BFA IOC level events
+ */
+enum bfa_ioc_aen_event {
+	BFA_IOC_AEN_HBGOOD	= 1,	/*  Heart Beat restore event	*/
+	BFA_IOC_AEN_HBFAIL	= 2,	/*  Heart Beat failure event	*/
+	BFA_IOC_AEN_ENABLE	= 3,	/*  IOC enabled event		*/
+	BFA_IOC_AEN_DISABLE	= 4,	/*  IOC disabled event		*/
+	BFA_IOC_AEN_FWMISMATCH	= 5,	/*  IOC firmware mismatch	*/
+};
+
+/**
+ * BFA IOC level event data, now just a place holder
+ */
+struct bfa_ioc_aen_data_s {
+	enum bfa_ioc_type_e ioc_type;
+	wwn_t	pwwn;
+	mac_t	mac;
+};
+
+#endif /* __BFA_DEFS_IOC_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_mfg.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_mfg.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_mfg.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_mfg.h	2009-10-31 21:34:48.733462000 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_DEFS_MFG_H__
+#define __BFA_DEFS_MFG_H__
+
+#include <bfa_os_inc.h>
+
+/**
+ * Manufacturing block version
+ */
+#define BFA_MFG_VERSION				1
+
+/**
+ * Manufacturing block format
+ */
+#define BFA_MFG_SERIALNUM_SIZE			11
+#define BFA_MFG_PARTNUM_SIZE			14
+#define BFA_MFG_SUPPLIER_ID_SIZE		10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE	20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE	20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE	4
+#define STRSZ(_n)	(((_n) + 4) & ~3)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN     256
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd_s {
+    u8     version;    /*  vpd data version */
+    u8     vpd_sig[3]; /*  characters 'V', 'P', 'D' */
+    u8     chksum;     /*  u8 checksum */
+    u8     vendor;     /*  vendor */
+    u8     len;        /*  vpd data length excluding header */
+    u8     rsv;
+    u8     data[BFA_MFG_VPD_LEN];  /*  vpd data */
+};
+
+#pragma pack(1)
+
+#endif /* __BFA_DEFS_MFG_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_pci.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_pci.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_pci.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_pci.h	2009-10-31 21:34:48.719462000 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFA_DEFS_PCI_H__
+#define __BFA_DEFS_PCI_H__
+
+/**
+ * PCI device and vendor ID information
+ */
+enum {
+	BFA_PCI_VENDOR_ID_BROCADE	= 0x1657,
+	BFA_PCI_DEVICE_ID_FC_8G2P	= 0x13,
+	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,
+	BFA_PCI_DEVICE_ID_CT		= 0x14,
+};
+
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
+};
+
+#define BFA_PCI_ACCESS_RANGES 1	/* Maximum number of device address ranges
+				 * mapped through different BAR(s). */
+
+#endif /* __BFA_DEFS_PCI_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_status.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_status.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_status.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_status.h	2009-10-31 21:34:48.753465000 -0700
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_DEFS_STATUS_H__
+#define __BFA_DEFS_STATUS_H__
+
+/**
+ * API status return values
+ *
+ * NOTE: The error msgs are auto generated from the comments. Only singe line
+ * comments are supported
+ */
+enum bfa_status {
+	BFA_STATUS_OK 		= 0,	/*  Success */
+	BFA_STATUS_FAILED 	= 1,	/*  Operation failed */
+	BFA_STATUS_EINVAL 	= 2,	/*  Invalid params Check input
+					 * parameters */
+	BFA_STATUS_ENOMEM 	= 3,	/*  Out of resources */
+	BFA_STATUS_ENOSYS 	= 4,	/*  Function not implemented */
+	BFA_STATUS_ETIMER 	= 5,	/*  Timer expired - Retry, if
+					 * persists, contact support */
+	BFA_STATUS_EPROTOCOL 	= 6,	/*  Protocol error */
+	BFA_STATUS_ENOFCPORTS 	= 7,	/*  No FC ports resources */
+	BFA_STATUS_NOFLASH 	= 8,	/*  Flash not present */
+	BFA_STATUS_BADFLASH 	= 9,	/*  Flash is corrupted or bad */
+	BFA_STATUS_SFP_UNSUPP 	= 10,	/*  Unsupported SFP - Replace SFP */
+	BFA_STATUS_UNKNOWN_VFID = 11,	/*  VF_ID not found */
+	BFA_STATUS_DATACORRUPTED = 12,	/*  Diag returned data corrupted
+					 * contact support */
+	BFA_STATUS_DEVBUSY 	= 13,	/*  Device busy - Retry operation */
+	BFA_STATUS_ABORTED 	= 14,	/*  Operation aborted */
+	BFA_STATUS_NODEV 	= 15,	/*  Dev is not present */
+	BFA_STATUS_HDMA_FAILED 	= 16,	/*  Host dma failed contact support */
+	BFA_STATUS_FLASH_BAD_LEN = 17,	/*  Flash bad length */
+	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
+	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
+	BFA_STATUS_FCPT_LS_RJT 	= 20,	/*  Got LS_RJT for FC Pass
+					 * through Req */
+	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
+	BFA_STATUS_VPORT_MAX 	= 22,	/*  Reached max VPORT supported
+					 * limit */
+	BFA_STATUS_UNSUPP_SPEED = 23,	/*  Invalid Speed Check speed
+					 * setting */
+	BFA_STATUS_INVLD_DFSZ 	= 24,	/*  Invalid Max data field size */
+	BFA_STATUS_CNFG_FAILED 	= 25,	/*  Setting can not be persisted */
+	BFA_STATUS_CMD_NOTSUPP 	= 26,	/*  Command/API not supported */
+	BFA_STATUS_NO_ADAPTER 	= 27,	/*  No Brocade Adapter Found */
+	BFA_STATUS_LINKDOWN 	= 28,	/*  Link is down - Check or replace
+					 * SFP/cable */
+	BFA_STATUS_FABRIC_RJT 	= 29,	/*  Reject from attached fabric */
+	BFA_STATUS_UNKNOWN_VWWN = 30,	/*  VPORT PWWN not found */
+	BFA_STATUS_NSLOGIN_FAILED = 31,	/*  Nameserver login failed */
+	BFA_STATUS_NO_RPORTS 	= 32,	/*  No remote ports found */
+	BFA_STATUS_NSQUERY_FAILED = 33,	/*  Nameserver query failed */
+	BFA_STATUS_PORT_OFFLINE = 34,	/*  Port is not online */
+	BFA_STATUS_RPORT_OFFLINE = 35,	/*  RPORT is not online */
+	BFA_STATUS_TGTOPEN_FAILED = 36,	/*  Remote SCSI target open failed */
+	BFA_STATUS_BAD_LUNS 	= 37,	/*  No valid LUNs found */
+	BFA_STATUS_IO_FAILURE 	= 38,	/*  SCSI target IO failure */
+	BFA_STATUS_NO_FABRIC 	= 39,	/*  No switched fabric present */
+	BFA_STATUS_EBADF 	= 40,	/*  Bad file descriptor */
+	BFA_STATUS_EINTR 	= 41,	/*  A signal was caught during ioctl */
+	BFA_STATUS_EIO 		= 42,	/*  I/O error */
+	BFA_STATUS_ENOTTY 	= 43,	/*  Inappropriate I/O control
+					 * operation */
+	BFA_STATUS_ENXIO 	= 44,	/*  No such device or address */
+	BFA_STATUS_EFOPEN 	= 45,	/*  Failed to open file */
+	BFA_STATUS_VPORT_WWN_BP = 46,	/*  WWN is same as base port's WWN */
+	BFA_STATUS_PORT_NOT_DISABLED = 47, /*  Port not disabled disable port
+					    * first */
+	BFA_STATUS_BADFRMHDR 	= 48,	/*  Bad frame header */
+	BFA_STATUS_BADFRMSZ 	= 49,	/*  Bad frame size check and replace
+					 * SFP/cable */
+	BFA_STATUS_MISSINGFRM 	= 50,	/*  Missing frame check and replace
+					 * SFP/cable */
+	BFA_STATUS_LINKTIMEOUT 	= 51,	/*  Link timeout check and replace
+					 * SFP/cable */
+	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/*  No FCP Nexus exists with the
+					 * rport */
+	BFA_STATUS_CHECKSUM_FAIL = 53,	/*  checksum failure */
+	BFA_STATUS_GZME_FAILED 	= 54,	/*  Get zone member query failed */
+	BFA_STATUS_SCSISTART_REQD = 55,	/*  SCSI disk require START command */
+	BFA_STATUS_IOC_FAILURE 	= 56,	/*  IOC failure - Retry, if persists
+					 * contact support */
+	BFA_STATUS_INVALID_WWN 	= 57,	/*  Invalid WWN */
+	BFA_STATUS_MISMATCH 	= 58,	/*  Version mismatch */
+	BFA_STATUS_IOC_ENABLED 	= 59,	/*  IOC is already enabled */
+	BFA_STATUS_ADAPTER_ENABLED = 60, /*  Adapter is not disabled disable
+					  * adapter first */
+	BFA_STATUS_IOC_NON_OP 	= 61,	/*  IOC is not operational. Enable IOC
+					 * and if it still fails,
+					 * contact support */
+	BFA_STATUS_ADDR_MAP_FAILURE = 62, /*  PCI base address not mapped
+					   * in OS */
+	BFA_STATUS_SAME_NAME 	= 63,	/*  Name exists! use a different
+					 * name */
+	BFA_STATUS_PENDING      = 64,   /*  API completes asynchronously */
+	BFA_STATUS_8G_SPD	= 65,	/*  Speed setting not valid for
+					 * 8G HBA */
+	BFA_STATUS_4G_SPD	= 66,	/*  Speed setting not valid for
+					 * 4G HBA */
+	BFA_STATUS_AD_IS_ENABLE = 67,	/*  Adapter is already enabled */
+	BFA_STATUS_EINVAL_TOV 	= 68,	/*  Invalid path failover TOV */
+	BFA_STATUS_EINVAL_QDEPTH = 69,	/*  Invalid queue depth value */
+	BFA_STATUS_VERSION_FAIL = 70,	/*  Application/Driver version
+					 * mismatch */
+	BFA_STATUS_DIAG_BUSY    = 71,	/*  diag busy */
+	BFA_STATUS_BEACON_ON	= 72,	/*  Port Beacon already on */
+	BFA_STATUS_BEACON_OFF	= 73,	/*  Port Beacon already off */
+	BFA_STATUS_LBEACON_ON   = 74,	/*  Link End-to-End Beacon already
+					 * on */
+	BFA_STATUS_LBEACON_OFF	= 75,	/*  Link End-to-End Beacon already
+					 * off */
+	BFA_STATUS_PORT_NOT_INITED = 76, /*  Port not initialized */
+	BFA_STATUS_RPSC_ENABLED = 77, /*  Target has a valid speed */
+	BFA_STATUS_ENOFSAVE = 78,	/*  No saved firmware trace */
+	BFA_STATUS_BAD_FILE = 79,	/*  Not a valid Brocade Boot Code
+					 * file */
+	BFA_STATUS_RLIM_EN = 80,	/*  Target rate limiting is already
+					 * enabled */
+	BFA_STATUS_RLIM_DIS = 81,  /*  Target rate limiting is already
+				    * disabled */
+	BFA_STATUS_IOC_DISABLED = 82,   /*  IOC is already disabled */
+	BFA_STATUS_ADAPTER_DISABLED = 83,   /*  Adapter is already disabled */
+	BFA_STATUS_BIOS_DISABLED = 84,   /*  Bios is already disabled */
+	BFA_STATUS_AUTH_ENABLED = 85,   /*  Authentication is already
+					 * enabled */
+	BFA_STATUS_AUTH_DISABLED = 86,   /*  Authentication is already
+					 * disabled */
+	BFA_STATUS_ERROR_TRL_ENABLED = 87,   /*  Target rate limiting is
+					      * enabled */
+	BFA_STATUS_ERROR_QOS_ENABLED = 88,   /*  QoS is enabled */
+	BFA_STATUS_NO_SFP_DEV = 89, /*  No SFP device check or replace SFP */
+	BFA_STATUS_MEMTEST_FAILED = 90,	/*  Memory test failed contact
+					 * support */
+	BFA_STATUS_INVALID_DEVID = 91,	/*  Invalid device id provided */
+	BFA_STATUS_QOS_ENABLED = 92, /*  QOS is already enabled */
+	BFA_STATUS_QOS_DISABLED = 93, /*  QOS is already disabled */
+	BFA_STATUS_INCORRECT_DRV_CONFIG = 94, /*  Check configuration
+					       * key/value pair */
+	BFA_STATUS_REG_FAIL = 95, /*  Can't read windows registry */
+	BFA_STATUS_IM_INV_CODE = 96, /*  Invalid IOCTL code */
+	BFA_STATUS_IM_INV_VLAN = 97, /*  Invalid VLAN ID */
+	BFA_STATUS_IM_INV_ADAPT_NAME = 98, /*  Invalid adapter name */
+	BFA_STATUS_IM_LOW_RESOURCES = 99, /*  Memory allocation failure in
+					   * driver */
+	BFA_STATUS_IM_VLANID_IS_PVID = 100, /*  Given VLAN id same as PVID */
+	BFA_STATUS_IM_VLANID_EXISTS = 101, /*  Given VLAN id already exists */
+	BFA_STATUS_IM_FW_UPDATE_FAIL = 102, /*  Updating firmware with new
+					     * VLAN ID failed */
+	BFA_STATUS_PORTLOG_ENABLED = 103, /*  Port Log is already enabled */
+	BFA_STATUS_PORTLOG_DISABLED = 104, /*  Port Log is already disabled */
+	BFA_STATUS_FILE_NOT_FOUND = 105, /*  Specified file could not be
+					  * found */
+	BFA_STATUS_QOS_FC_ONLY = 106, /*  QOS can be enabled for FC mode
+				       * only */
+	BFA_STATUS_RLIM_FC_ONLY = 107, /*  RATELIM can be enabled for FC mode
+					* only */
+	BFA_STATUS_CT_SPD = 108, /*  Invalid speed selection for Catapult. */
+	BFA_STATUS_LEDTEST_OP = 109, /*  LED test is operating */
+	BFA_STATUS_CEE_NOT_DN = 110, /*  eth port is not at down state, please
+				      * bring down first */
+	BFA_STATUS_10G_SPD = 111, /*  Speed setting not valid for 10G HBA */
+	BFA_STATUS_IM_INV_TEAM_NAME = 112, /*  Invalid team name */
+	BFA_STATUS_IM_DUP_TEAM_NAME = 113, /*  Given team name already
+					    * exists */
+	BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, /*  Given adapter is part
+						    * of another team */
+	BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, /*  Adapter has VLANs configured.
+					      * Delete all VLANs before
+					      * creating team */
+	BFA_STATUS_IM_PVID_MISMATCH = 116, /*  Mismatching PVIDs configured
+					    * for adapters */
+	BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, /*  Mismatching link speeds
+						  * configured for adapters */
+	BFA_STATUS_IM_MTU_MISMATCH = 118, /*  Mismatching MTUs configured for
+					   * adapters */
+	BFA_STATUS_IM_RSS_MISMATCH = 119, /*  Mismatching RSS parameters
+					   * configured for adapters */
+	BFA_STATUS_IM_HDS_MISMATCH = 120, /*  Mismatching HDS parameters
+					   * configured for adapters */
+	BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, /*  Mismatching offload
+					       * parameters configured for
+					       * adapters */
+	BFA_STATUS_IM_PORT_PARAMS = 122, /*  Error setting port parameters */
+	BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, /*  Port is not part of team */
+	BFA_STATUS_IM_CANNOT_REM_PRI = 124, /*  Primary adapter cannot be
+					     * removed. Change primary before
+					     * removing */
+	BFA_STATUS_IM_MAX_PORTS_REACHED = 125, /*  Exceeding maximum ports
+						* per team */
+	BFA_STATUS_IM_LAST_PORT_DELETE = 126, /*  Last port in team being
+					       * deleted */
+	BFA_STATUS_IM_NO_DRIVER = 127, /*  IM driver is not installed */
+	BFA_STATUS_IM_MAX_VLANS_REACHED = 128, /*  Exceeding maximum VLANs
+						* per port */
+	BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, /* Bios speed config not
+						  * allowed for CNA */
+	BFA_STATUS_NO_MINPORT_DRIVER = 130, /*  Miniport driver is not
+					     * loaded */
+	BFA_STATUS_CARD_TYPE_MISMATCH = 131, /*  Card type mismatch */
+	BFA_STATUS_BAD_ASICBLK = 132, /*  Bad ASIC block */
+	BFA_STATUS_NO_DRIVER = 133, /*  Storage/Ethernet driver not loaded */
+	BFA_STATUS_INVALID_MAC = 134, /*  Invalid mac address */
+	BFA_STATUS_IM_NO_VLAN = 135, /*  No VLANs configured on the adapter */
+	BFA_STATUS_IM_ETH_LB_FAILED = 136, /*  Ethernet loopback test failed */
+	BFA_STATUS_IM_PVID_REMOVE = 137, /*  Cannot remove port vlan (PVID) */
+	BFA_STATUS_IM_PVID_EDIT = 138, /*  Cannot edit port vlan (PVID) */
+	BFA_STATUS_CNA_NO_BOOT = 139, /*  Boot upload not allowed for CNA */
+	BFA_STATUS_IM_PVID_NON_ZERO = 140, /*  Port VLAN ID (PVID) is Set to
+					    * Non-Zero Value */
+	BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, /*  Acquiring Network
+						  * Subsytem Lock Failed.Please
+						  * try after some time */
+	BFA_STATUS_IM_GET_INETCFG_FAILED = 142, /*  Acquiring Network Subsytem
+						 * handle Failed. Please try
+						 * after some time */
+	BFA_STATUS_IM_NOT_BOUND = 143, /*  Brocade 10G Ethernet Service is not
+					* Enabled on this port */
+	BFA_STATUS_INSUFFICIENT_PERMS = 144, /*  User doesn't have sufficient
+					      * permissions to execute the BCU
+					      * application */
+	BFA_STATUS_IM_INV_VLAN_NAME = 145, /*  Invalid/Reserved Vlan name
+					    * string. The name is not allowed
+					    * for the normal Vlans */
+	BFA_STATUS_CMD_NOTSUPP_CNA = 146, /*  Command not supported for CNA */
+	BFA_STATUS_IM_PASSTHRU_EDIT = 147, /*  Can not edit passthru vlan id */
+	BFA_STATUS_IM_BIND_FAILED = 148, /*! < IM Driver bind operation
+					  * failed */
+	BFA_STATUS_IM_UNBIND_FAILED = 149, /* ! < IM Driver unbind operation
+					    * failed */
+	BFA_STATUS_MAX_VAL		/*  Unknown error code */
+};
+#define bfa_status_t enum bfa_status
+
+enum bfa_eproto_status {
+	BFA_EPROTO_BAD_ACCEPT = 0,
+	BFA_EPROTO_UNKNOWN_RSP = 1
+};
+#define bfa_eproto_status_t enum bfa_eproto_status
+
+#endif /* __BFA_DEFS_STATUS_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_types.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_types.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_types.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_types.h	2009-10-31 21:34:48.764462000 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_DEFS_TYPES_H__
+#define __BFA_DEFS_TYPES_H__
+
+#include <bfa_os_inc.h>
+
+enum bfa_boolean {
+	BFA_FALSE = 0,
+	BFA_TRUE  = 1
+};
+#define bfa_boolean_t enum bfa_boolean
+
+#define BFA_STRING_32	32
+
+#endif /* __BFA_DEFS_TYPES_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_version.h net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_version.h
--- net-next-2.6-orig/drivers/net/bna/include/defs/bfa_defs_version.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/defs/bfa_defs_version.h	2009-10-31 21:34:48.726462000 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_DEFS_VERSION_H__
+#define __BFA_DEFS_VERSION_H__
+
+#define BFA_VERSION_LEN		64
+
+#endif
diff -ruP net-next-2.6-orig/drivers/net/bna/include/protocol/types.h net-next-2.6-mod/drivers/net/bna/include/protocol/types.h
--- net-next-2.6-orig/drivers/net/bna/include/protocol/types.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/include/protocol/types.h	2009-10-31 21:34:48.801464000 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ *  types.h Protocol defined base types
+ */
+
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <bfa_os_inc.h>
+
+#define wwn_t u64
+#define lun_t u64
+
+#define WWN_NULL	(0)
+#define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
+#define FC_ALPA_MAX	128
+
+#pragma pack(1)
+
+#define MAC_ADDRLEN	(6)
+struct mac_s { u8 mac[MAC_ADDRLEN]; };
+#define mac_t struct mac_s
+
+#pragma pack()
+
+#endif

^ permalink raw reply

* Subject: [PATCH 4/6] bna: Brocade 10Gb Ethernet device driver
From: Rasesh Mody @ 2009-11-01  5:03 UTC (permalink / raw)
  To: netdev; +Cc: adapter_linux_open_src_team

From: Rasesh Mody <rmody@brocade.com>

This is patch 4/6 which contains linux driver source for
Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
Re-based source against net-next-2.6 and re-submitting the
patch with few fixes.

We wish this patch to be considered for inclusion in net-next-2.6

Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
 bfa_ioc.h    |  266 ++++++
 bfa_os_inc.h |  210 +++++
 bfa_timer.h  |   60 +
 bna.h        | 2300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bna_hwreg.h  | 1004 +++++++++++++++++++++++++
 bna_intr.h   |   96 ++
 6 files changed, 3936 insertions(+)

diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_ioc.h net-next-2.6-mod/drivers/net/bna/bfa_ioc.h
--- net-next-2.6-orig/drivers/net/bna/bfa_ioc.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_ioc.h	2009-10-31 21:34:48.184532000 -0700
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+#ifndef __BFA_IOC_H__
+#define __BFA_IOC_H__
+
+#include <cs/bfa_sm.h>
+#include <bfi/bfi.h>
+#include <bfi/bfi_ioc.h>
+#include <bfi/bfi_boot.h>
+#include <bfa_timer.h>
+
+/**
+ * PCI device information required by IOC
+ */
+struct bfa_pcidev_s {
+	int             pci_slot;
+	u8         pci_func;
+	u16	device_id;
+	bfa_os_addr_t   pci_bar_kva;
+};
+
+/**
+ * Structure used to remember the DMA-able memory block's KVA and Physical
+ * Address
+ */
+struct bfa_dma_s {
+	void		*kva;	/*! Kernel virtual address	*/
+	u64	pa;	/*! Physical address		*/
+};
+
+#define BFA_DMA_ALIGN_SZ	256
+#define BFA_ROUNDUP(_l, _s)	(((_l) + ((_s) - 1)) & ~((_s) - 1))
+
+
+
+#define bfa_dma_addr_set(dma_addr, pa)	\
+		__bfa_dma_addr_set(&dma_addr, (u64)pa)
+
+static inline void
+__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+	dma_addr->a32.addr_lo = (u32) pa;
+	dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa));
+}
+
+
+#define bfa_dma_be_addr_set(dma_addr, pa)	\
+		__bfa_dma_be_addr_set(&dma_addr, (u64)pa)
+static inline void
+__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+	dma_addr->a32.addr_lo = (u32) bfa_os_htonl(pa);
+	dma_addr->a32.addr_hi = (u32) bfa_os_htonl(bfa_os_u32(pa));
+}
+
+struct bfa_ioc_regs_s {
+	bfa_os_addr_t   hfn_mbox_cmd;
+	bfa_os_addr_t   hfn_mbox;
+	bfa_os_addr_t   lpu_mbox_cmd;
+	bfa_os_addr_t   lpu_mbox;
+	bfa_os_addr_t   pss_ctl_reg;
+	bfa_os_addr_t   app_pll_fast_ctl_reg;
+	bfa_os_addr_t   app_pll_slow_ctl_reg;
+	bfa_os_addr_t   ioc_sem_reg;
+	bfa_os_addr_t   ioc_usage_sem_reg;
+	bfa_os_addr_t   ioc_usage_reg;
+	bfa_os_addr_t   host_page_num_fn;
+	bfa_os_addr_t   heartbeat;
+	bfa_os_addr_t   ioc_fwstate;
+	bfa_os_addr_t   ll_halt;
+	bfa_os_addr_t   shirq_isr_next;
+	bfa_os_addr_t   shirq_msk_next;
+	bfa_os_addr_t   smem_page_start;
+	u32	smem_pg0;
+};
+
+#define bfa_reg_read(_raddr)	bfa_os_reg_read(_raddr)
+#define bfa_reg_write(_raddr, _val)	bfa_os_reg_write(_raddr, _val)
+#define bfa_mem_read(_raddr, _off)	bfa_os_mem_read(_raddr, _off)
+#define bfa_mem_write(_raddr, _off, _val)	\
+					bfa_os_mem_write(_raddr, _off, _val)
+/**
+ * IOC Mailbox structures
+ */
+struct bfa_mbox_cmd_s {
+	struct list_head		qe;
+	u32	msg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * IOC mailbox module
+ */
+typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m);
+struct bfa_ioc_mbox_mod_s {
+	struct list_head	cmd_q;		/*  pending mbox queue	*/
+	int		nmclass;	/*  number of handlers */
+	struct {
+		bfa_ioc_mbox_mcfunc_t	cbfn;	/*  message handlers	*/
+		void			*cbarg;
+	} mbhdlr[BFI_MC_MAX];
+};
+
+/**
+ * IOC callback function interfaces
+ */
+typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status);
+typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa);
+struct bfa_ioc_cbfn_s {
+	bfa_ioc_enable_cbfn_t	enable_cbfn;
+	bfa_ioc_disable_cbfn_t	disable_cbfn;
+	bfa_ioc_hbfail_cbfn_t	hbfail_cbfn;
+	bfa_ioc_reset_cbfn_t	reset_cbfn;
+};
+
+/**
+ * Heartbeat failure notification queue element.
+ */
+struct bfa_ioc_hbfail_notify_s {
+	struct list_head		qe;
+	bfa_ioc_hbfail_cbfn_t	cbfn;
+	void			*cbarg;
+};
+
+/**
+ * Initialize a heartbeat failure notification structure
+ */
+#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do {	\
+	(__notify)->cbfn = (__cbfn);      \
+	(__notify)->cbarg = (__cbarg);      \
+} while (0)
+
+struct bfa_ioc_s {
+	bfa_fsm_t		fsm;
+	struct bfa_s		*bfa;
+	struct bfa_pcidev_s	pcidev;
+	struct bfa_timer_mod_s 	*timer_mod;
+	struct bfa_timer_s 	ioc_timer;
+	struct bfa_timer_s 	sem_timer;
+	u32		hb_count;
+	u32		hb_fail;
+	u32		retry_count;
+	struct list_head		hb_notify_q;
+	void			*dbg_fwsave;
+	int			dbg_fwsave_len;
+	bfa_boolean_t		dbg_fwsave_once;
+	enum bfi_mclass		ioc_mc;
+	struct bfa_ioc_regs_s 	ioc_regs;
+	struct bfa_trc_mod_s	*trcmod;
+	struct bfa_aen_s	*aen;
+	struct bfa_log_mod_s	*logm;
+	struct bfa_ioc_drv_stats_s	stats;
+	bfa_boolean_t		auto_recover;
+	bfa_boolean_t		fcmode;
+	bfa_boolean_t		ctdev;
+	bfa_boolean_t		cna;
+	bfa_boolean_t		pllinit;
+	u8			port_id;
+
+	struct bfa_dma_s	attr_dma;
+	struct bfi_ioc_attr_s	*attr;
+	struct bfa_ioc_cbfn_s	*cbfn;
+	struct bfa_ioc_mbox_mod_s mbox_mod;
+};
+
+#define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
+#define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)
+#define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)
+#define bfa_ioc_portid(__ioc)		((__ioc)->port_id)
+#define bfa_ioc_fetch_stats(__ioc, __stats) \
+		(((__stats)->drv_stats) = (__ioc)->stats)
+#define bfa_ioc_clr_stats(__ioc)	\
+		bfa_os_memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
+#define bfa_ioc_maxfrsize(__ioc)	((__ioc)->attr->maxfrsize)
+#define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)
+#define bfa_ioc_speed_sup(__ioc)	\
+	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
+
+/**
+ * IOC mailbox interface
+ */
+void bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd);
+void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc,
+		bfa_ioc_mbox_mcfunc_t *mcfuncs);
+void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc);
+void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len);
+void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
+void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
+		bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
+
+/**
+ * IOC interfaces
+ */
+void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
+		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod,
+		struct bfa_trc_mod_s *trcmod,
+		struct bfa_aen_s *aen, struct bfa_log_mod_s *logm);
+void bfa_ioc_detach(struct bfa_ioc_s *ioc);
+void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
+		enum bfi_mclass mc);
+u32 bfa_ioc_meminfo(void);
+void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa);
+void bfa_ioc_enable(struct bfa_ioc_s *ioc);
+void bfa_ioc_disable(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
+
+void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param);
+void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
+void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
+void bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t intx);
+bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
+void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc);
+void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr);
+void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
+		struct bfa_adapter_attr_s *ad_attr);
+int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover);
+void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave);
+bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,
+		int *trclen);
+bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
+				 int *trclen);
+u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
+u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
+void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
+void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
+	struct bfa_ioc_hbfail_notify_s *notify);
+
+/*
+ * bfa mfg wwn API functions
+ */
+wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc);
+wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc);
+wwn_t bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst);
+mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc);
+u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
+
+#endif /* __BFA_IOC_H__ */
+
diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_os_inc.h net-next-2.6-mod/drivers/net/bna/bfa_os_inc.h
--- net-next-2.6-orig/drivers/net/bna/bfa_os_inc.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_os_inc.h	2009-10-31 21:34:48.191532000 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+
+/**
+ * Contains declarations all OS Specific files needed for BFA layer
+ */
+
+#ifndef __BFA_OS_INC_H__
+#define __BFA_OS_INC_H__
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#else
+#include <linux/types.h>
+
+#include <linux/version.h>
+#include <linux/pci.h>
+
+#include <linux/dma-mapping.h>
+#define SET_MODULE_VERSION(VER)
+
+#include <linux/idr.h>
+
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+
+#include <linux/workqueue.h>
+
+
+
+#define BFA_ERR			KERN_ERR
+#define BFA_WARNING		KERN_WARNING
+#define BFA_NOTICE		KERN_NOTICE
+#define BFA_INFO		KERN_INFO
+#define BFA_DEBUG		KERN_DEBUG
+
+#define LOG_BFAD_INIT		0x00000001
+#define LOG_FCP_IO		0x00000002
+
+#ifdef DEBUG
+#define BFA_DEV_TRACE(bfad, level, fmt, arg...)				\
+		BFA_DEV_PRINTF(bfad, level, fmt, ## arg)
+#define BFA_TRACE(level, fmt, arg...)					\
+		BFA_PRINTF(level, fmt, ## arg)
+#else
+#define BFA_DEV_TRACE(bfad, level, fmt, arg...)
+#define BFA_TRACE(level, fmt, arg...)
+#endif
+
+#define BFA_ASSERT(p) do {						\
+	if (!(p)) {      \
+		printk(KERN_ERR "assert(%s) failed at %s:%d\n",		\
+		#p, __FILE__, __LINE__);      \
+		BUG();      \
+	}								\
+} while (0)
+
+
+#ifndef BFA_DEV_PRINTF
+#define BFA_DEV_PRINTF(bfad, level, fmt, arg...)			\
+		dev_printk(level, &(((struct bfad_s *)			\
+			(bfad))->pcidev->dev), fmt, ##arg);
+#endif
+
+#define BFA_PRINTF(level, fmt, arg...)					\
+		printk(level fmt, ##arg);
+
+int bfa_os_MWB(void *);
+
+#define bfa_os_mmiowb()		mmiowb()
+
+#define bfa_swap_3b(_x)				\
+	((((_x) & 0xff) << 16) |		\
+	((_x) & 0x00ff00) |			\
+	(((_x) & 0xff0000) >> 16))
+
+#define bfa_swap_8b(_x) 				\
+     ((((_x) & 0xff00000000000000ull) >> 56)		\
+      | (((_x) & 0x00ff000000000000ull) >> 40)		\
+      | (((_x) & 0x0000ff0000000000ull) >> 24)		\
+      | (((_x) & 0x000000ff00000000ull) >> 8)		\
+      | (((_x) & 0x00000000ff000000ull) << 8)		\
+      | (((_x) & 0x0000000000ff0000ull) << 24)		\
+      | (((_x) & 0x000000000000ff00ull) << 40)		\
+      | (((_x) & 0x00000000000000ffull) << 56))
+
+#define bfa_os_swap32(_x) 			\
+	((((_x) & 0xff) << 24) 		|	\
+	(((_x) & 0x0000ff00) << 8)	|	\
+	(((_x) & 0x00ff0000) >> 8)	|	\
+	(((_x) & 0xff000000) >> 24))
+
+
+#ifndef __BIGENDIAN
+#define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
+				 (((_x) & 0x00ff) << 8)))
+
+#define bfa_os_htonl(_x)	bfa_os_swap32(_x)
+#define bfa_os_htonll(_x)	bfa_swap_8b(_x)
+#define bfa_os_hton3b(_x)	bfa_swap_3b(_x)
+
+#define bfa_os_wtole(_x)   (_x)
+
+#else
+
+#define bfa_os_htons(_x)   (_x)
+#define bfa_os_htonl(_x)   (_x)
+#define bfa_os_hton3b(_x)  (_x)
+#define bfa_os_htonll(_x)  (_x)
+#define bfa_os_wtole(_x)   bfa_os_swap32(_x)
+
+#endif
+
+#define bfa_os_ntohs(_x)   bfa_os_htons(_x)
+#define bfa_os_ntohl(_x)   bfa_os_htonl(_x)
+#define bfa_os_ntohll(_x)  bfa_os_htonll(_x)
+#define bfa_os_ntoh3b(_x)  bfa_os_hton3b(_x)
+
+#define bfa_os_u32(__pa64) ((__pa64) >> 32)
+
+#define bfa_os_memset	memset
+#define bfa_os_memcpy	memcpy
+#define bfa_os_udelay	udelay
+#define bfa_os_vsprintf vsprintf
+
+#define bfa_os_assign(__t, __s) __t = __s
+
+#define bfa_os_addr_t char __iomem *
+#define bfa_os_panic()
+
+#define bfa_os_reg_read(_raddr) bfa_os_wtole(readl(_raddr))
+#define bfa_os_reg_write(_raddr, _val) writel(bfa_os_wtole((_val)), (_raddr))
+#define bfa_os_mem_read(_raddr, _off)                                   \
+	bfa_os_ntohl(readl(((_raddr) + (_off))))
+#define bfa_os_mem_write(_raddr, _off, _val)                            \
+	writel(bfa_os_htonl((_val)), ((_raddr) + (_off)))
+
+#define BFA_TRC_TS(_trcm)						\
+			({						\
+				struct timeval tv;			\
+									\
+				do_gettimeofday(&tv);      \
+				(tv.tv_sec*1000000+tv.tv_usec);      \
+			 })
+
+#endif
+
+#define boolean_t int
+
+/**
+ * For current time stamp, OS API will fill-in
+ */
+struct bfa_timeval_s {
+	u32	tv_sec;		/*  seconds        */
+	u32	tv_usec;	/*  microseconds   */
+};
+
+void bfa_os_gettimeofday(struct bfa_timeval_s *tv);
+
+static inline void
+wwn2str(char *wwn_str, u64 wwn)
+{
+	union {
+		u64 wwn;
+		u8 byte[8];
+	} w;
+
+	w.wwn = wwn;
+	sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
+		w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
+		w.byte[6], w.byte[7]);
+}
+
+static inline void
+fcid2str(char *fcid_str, u32 fcid)
+{
+	union {
+		u32 fcid;
+		u8 byte[4];
+	} f;
+
+	f.fcid = fcid;
+	sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
+}
+
+#endif /* __BFA_OS_INC_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bfa_timer.h net-next-2.6-mod/drivers/net/bna/bfa_timer.h
--- net-next-2.6-orig/drivers/net/bna/bfa_timer.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bfa_timer.h	2009-10-31 21:34:48.198532000 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ */
+#ifndef __BFA_TIMER_H__
+#define __BFA_TIMER_H__
+
+#include <bfa_os_inc.h>
+#include <cs/bfa_q.h>
+
+struct bfa_s;
+
+typedef void (*bfa_timer_cbfn_t)(void *);
+
+/**
+ * BFA timer data structure
+ */
+struct bfa_timer_s {
+	struct list_head	qe;
+	bfa_timer_cbfn_t timercb;
+	void            *arg;
+	int             timeout;	/**< in millisecs. */
+};
+
+/**
+ * Timer module structure
+ */
+struct bfa_timer_mod_s {
+	struct list_head timer_q;
+};
+
+#define BFA_TIMER_FREQ 500 /**< specified in millisecs */
+
+void bfa_timer_beat(struct bfa_timer_mod_s *mod);
+void bfa_timer_init(struct bfa_timer_mod_s *mod);
+void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+			bfa_timer_cbfn_t timercb, void *arg,
+			unsigned int timeout);
+void bfa_timer_stop(struct bfa_timer_s *timer);
+
+#endif /* __BFA_TIMER_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bna.h net-next-2.6-mod/drivers/net/bna/bna.h
--- net-next-2.6-orig/drivers/net/bna/bna.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna.h	2009-10-31 21:34:48.206538000 -0700
@@ -0,0 +1,2300 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ *    Copyright (c) 2008- Brocade Communications Systems, Inc.
+ *    All rights reserved.
+ *
+ *    @file bna.h
+ *    BNA Exported Definitions & Prototypes
+ */
+
+#ifndef __BNA_H__
+#define __BNA_H__
+
+#include <bna_os.h>
+#include <cna.h>
+#include <bfa_timer.h>
+#include <bfa_ioc.h>
+#include <cna/pstats/phyport_defs.h>
+#include <cna/pstats/ethport_defs.h>
+#include <cee/bfa_cee.h>
+
+#define BNA_VLAN_ID_MAX 	4095
+
+#define BNA_TXQ_ID_MAX  	64
+#define BNA_RXQ_ID_MAX  	64
+#define BNA_CQ_ID_MAX   	64
+
+#define BNA_IB_ID_MAX   	128
+#define BNA_RIT_SIZE		256
+#define BNA_RIT_ID_MAX  	64
+
+#define BNA_UCAST_TABLE_SIZE	256
+#define BNA_MCAST_TABLE_SIZE	256
+
+#define BNA_HW_STATS_SIZE   	16384
+#define BNA_DEFAULT_RXF_ID  	0
+#define BNA_DEFAULT_TXF_ID  	0
+
+#define BNA_RXF_ID_NONE		255
+
+#define LOG_CRITICAL_LEVEL  1
+#define LOG_ERROR_LEVEL     2
+#define LOG_WARN_LEVEL      5
+#define LOG_INFO_LEVEL      6
+#define LOG_DEBUG_LEVEL     7
+
+struct bna_dma_addr {
+	u32	msb;
+	u32	lsb;
+};
+
+struct bna_dma_addr_le {
+	u32	le_lsb;
+	u32	le_msb;
+};
+
+#define BNA_MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+#define BNA_MAC_IS_MULTICAST(_mac_ms_octet)	\
+					((_mac_ms_octet) & 0x01)
+#define BNA_MAC_IS_UNICAST(_mac_ms_octet)	\
+			(!BNA_MAC_IS_MULTICAST((_mac_ms_octet)))
+
+#define BNA_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
+#define BNA_TO_POWER_OF_2(x)		\
+do {					\
+	int _shift = 0;			\
+	while ((x) && (x) != 1) {      \
+		(x) >>= 1;		\
+		_shift++;		\
+	}				\
+	(x) <<= _shift;			\
+} while (0)
+
+#define BNA_TO_POWER_OF_2_HIGH(x)       \
+do {                                    \
+		int n = 1;                      \
+		while (n < (x)) {      \
+			n <<= 1;                \
+		}                               \
+		(x) = n;                        \
+} while (0)
+
+/**
+ * BNA_SET_DMA_ADDR()
+ *
+ *  Converts a dma address _addr from the host
+ *  endian format to the bna_dma_addr_t format.
+ *
+ * @param[in] _addr 	- DMA'able address in host endian format
+ * @param[in] _bna_dma_addr - Pointer to bna_dma_addr_t where address
+ *  			- will be stored.
+ */
+#define BNA_SET_DMA_ADDR(_addr, _bna_dma_addr)  			\
+do {									\
+	u64 tmp_addr = 						\
+	bna_os_dma_addr64((u64)(_addr));      \
+	(_bna_dma_addr)->msb = ((struct bna_dma_addr *)&tmp_addr)->msb;	\
+	(_bna_dma_addr)->lsb = ((struct bna_dma_addr *)&tmp_addr)->lsb;	\
+} while (0)
+
+/**
+ * BNA_GET_DMA_ADDR()
+ *
+ *  Converts a dma address _addr from the host
+ *  endian format to the bna_dma_addr_t format.
+ *
+ * @parma[in] _bna_dma_addr	- Pointer to bna_dma_addr_t where address will
+ * 				be stored.
+ * @param[in] _addr 		- DMA'able address in host endian format
+ */
+#define BNA_GET_DMA_ADDR(_bna_dma_addr, _addr)  			\
+do {									\
+	(_addr) = ((u64)(bna_os_ntohl((_bna_dma_addr)->msb)) << 32)\
+		| ((bna_os_ntohl((_bna_dma_addr)->lsb) & 0xffffffff));      \
+} while (0)
+
+/**
+ * BNA_ALIGN()
+ *
+ *	Aligns a size to a given value
+ *
+ * @param[in] _x	- Actual size to align
+ * @param[in] _a	- Value to which size should be aligned
+ *
+ */
+#define BNA_ALIGN(x, a)     (((x) + (a) - 1) & ~((a) - 1))
+
+enum bna_enable_e {BNA_DISABLE = 0, BNA_ENABLE = 1};
+
+enum bna_status_e {
+	BNA_OK = 0,
+	BNA_FAIL = 1,
+	BNA_DUPLICATE = 2,
+	BNA_BUSY = 3
+};
+
+enum {
+    BNA_FALSE = 0,
+    BNA_TRUE = 1
+};
+
+#define BNA_LARGE_PKT_SIZE 1000
+/**
+ * This structure is for dynamic interrupt moderation
+ * Should be part of the driver private structure.
+ */
+struct bna_pkt_rate {
+	u32 small_pkt_cnt;
+	u32 large_pkt_cnt;
+};
+#define BNA_UPDATE_PKT_CNT(_pkt, _len)		\
+do {						\
+	if ((_len) > BNA_LARGE_PKT_SIZE) {      \
+		(_pkt)->large_pkt_cnt++;	\
+	} else {				\
+		(_pkt)->small_pkt_cnt++;	\
+	}					\
+} while (0)
+
+/**
+ *  BNA callback function prototype The driver registers this
+ *  callback with BNA. This is called from the mailbox/error
+ *  handler routine of BNA, for further driver processing.
+ *
+ * @param[in] cbarg - Opaque cookie used by the driver to identify the callback.
+ * @param[in] cmd_code - Command code for the callback
+ * @param[in] status - Status as returned by the f/w
+ *
+ * @return    void
+ */
+
+typedef void (*bna_cbfn_t)(void *cbarg, u8 status);
+typedef void (*bna_diag_cbfn_t)(void *cbarg, void *data, u8 status);
+
+/**
+ *	Structure of callbacks implemented by the driver
+ */
+struct bna_mbox_cbfn {
+	bna_cbfn_t	ucast_set_cb;
+	bna_cbfn_t	ucast_add_cb;
+	bna_cbfn_t	ucast_del_cb;
+
+	bna_cbfn_t	mcast_add_cb;
+	bna_cbfn_t	mcast_del_cb;
+	bna_cbfn_t	mcast_filter_cb;
+	bna_cbfn_t	mcast_del_all_cb;
+
+	bna_cbfn_t	set_promisc_cb;
+	bna_cbfn_t	set_default_cb;
+
+	bna_cbfn_t	txq_stop_cb;
+	bna_cbfn_t	rxq_stop_cb;
+
+	bna_cbfn_t	port_admin_cb;
+	bna_cbfn_t	link_up_cb;
+	bna_cbfn_t	link_down_cb;
+
+	bna_cbfn_t	stats_get_cb;
+	bna_cbfn_t	stats_clr_cb;
+
+	bna_cbfn_t	hw_error_cb;
+
+	bna_cbfn_t      lldp_get_cfg_cb;
+	bna_cbfn_t      cee_get_stats_cb;
+
+	bna_cbfn_t	set_diag_lb_cb;	/* Diagnostics */
+
+	bna_cbfn_t	set_pause_cb;
+
+	bna_cbfn_t	mtu_info_cb;
+
+	bna_cbfn_t	rxf_cb;
+
+	bna_diag_cbfn_t	diag_get_temp_cb;
+	bna_diag_cbfn_t	diag_sfpshow_cb;
+	bna_diag_cbfn_t	diag_fwping_cb;
+	bna_diag_cbfn_t	diag_ledtest_cb;
+};
+
+struct bna_chip_regs_offset {
+	u32 page_addr;
+	u32 fn_int_status;
+	u32 fn_int_mask;
+	u32 msix_idx;
+};
+/**
+ * Memory mapped addresses of often used chip registers
+ */
+struct bna_chip_regs{
+	u8 *page_addr;
+	u8 *fn_int_status;
+	u8 *fn_int_mask;
+};
+
+#define BNA_MAX_MBOX_CMD_QUEUE  256
+#define BNA_MAX_MBOX_CMD_LEN	(BFI_IOC_MSGSZ * 4) /* 32 bytes */
+
+struct bna_mbox_cmd_qe {
+	struct bfa_mbox_cmd_s	cmd;
+	u32 cmd_len;	   /*  Length of the message in bytes */
+	void 	*cbarg;		/* non-default callback argument */
+};
+
+struct bna_mbox_q {
+	u32 producer_index;
+	u32 consumer_index;
+	void 	*posted;	/* Pointer to the posted element */
+	struct 	bna_mbox_cmd_qe mb_qe[BNA_MAX_MBOX_CMD_QUEUE];
+};
+
+/**
+ * BNA device structure
+ */
+struct bna_dev_s {
+	u8		*bar0;
+
+	u8		pci_fn;
+	u8		port;
+
+	u8		rxf_promiscuous_id;
+	u8		rxf_default_id;
+	u8		rit_size[BNA_RIT_ID_MAX];
+	u32	vlan_table[BNA_RXF_ID_MAX][(BNA_VLAN_ID_MAX + 1) / 32];
+	enum bna_enable_e	vlan_filter_enable[BNA_RXF_ID_MAX];
+	u64	rxf_active;
+	u64	txf_active;
+	u64	rxf_active_last;
+	u64	txf_active_last;
+
+	struct bfi_ll_stats  *hw_stats;
+	struct bna_dma_addr hw_stats_dma;
+
+	struct bna_stats  stats;
+
+	u32	mcast_47_32[BNA_MCAST_TABLE_SIZE];
+	u32	mcast_31_0[BNA_MCAST_TABLE_SIZE];
+
+	u32	tmp_mc_47_32[BNA_MCAST_TABLE_SIZE];
+	u32	tmp_mc_31_0[BNA_MCAST_TABLE_SIZE];
+
+	u32	rxa_arb_pri;	/* RxA Arbitration Priority */
+
+	struct bna_chip_regs regs;	/* Pointer to oft used registers */
+
+	struct bna_mbox_q mbox_q;
+	struct bna_mbox_cbfn	mb_cbfns;
+	void		*cbarg;		/* Argument to callback function */
+
+	/* IOC integration */
+	struct bfa_ioc_s 	ioc;
+	struct bfa_timer_mod_s 	timer_mod;
+	struct bfa_trc_mod_s	*trcmod;
+	struct bna_pkt_rate 	pkt_rate;  /* Packet rate structure */
+	u8			ioc_disable_pending;
+
+
+	u16		msg_ctr; /* Counter for mailbox messages posted */
+	struct bfa_cee_s 	*cee;
+};
+
+#define bna_get_handle_size() (sizeof(struct bna_dev_s))
+
+u8 bna_calc_coalescing_timer(struct bna_dev_s *dev, struct bna_pkt_rate *pkt);
+
+/**
+ * bna_reg_read()
+ *
+ *	Function to read the value of a register.
+ *	Returns value in little-endian format.
+ *
+ * @param[in] _raddr	- Absolute address of the register to read
+ *
+ * @return    u32	- Value of the register read
+ */
+#define bna_reg_read(_raddr)	bna_os_reg_read(_raddr)
+
+/**
+ * bna_reg_write()
+ *
+ *	Function to write the value to a register.
+ *	Writes in little-endian format.
+ *
+ * @param[in] _raddr	- Absolute address of the register to write.
+ * @param[in] _val	- Value to be written.
+ *
+ * @return    void
+ */
+#define bna_reg_write(_raddr, _val) bna_os_reg_write(_raddr, _val)
+
+/**
+ * bna_mem_readw()
+ *
+ *	Function to read the value of a memory location word by word.
+ *	Returns value in big-endian format.
+ *
+ * @param[in] _raddr	- Absolute address of the memory location to read.
+ *
+ * @return    u32	- Value (word) of the memory location read.
+ */
+/* #define bna_mem_readw(_raddr)	  bna_os_mem_readw(_raddr) */
+#define bna_mem_readw(_raddr)	  bna_os_reg_read(_raddr)
+
+/**
+ * bna_mem_writew()
+ *
+ *	Function to write a value to a given memory location.
+ *	Writes in big-endian format.
+ *
+ * @param[in] _raddr	- Absolute address of the memory location to write.
+ * @param[in] _val	- Value to be written.
+ *
+ * @return    void
+ */
+/* #define bna_mem_writew(_raddr, _val)	bna_os_mem_writew(_raddr, _val) */
+#define bna_mem_writew(_raddr, _val)	bna_os_reg_write(_raddr, _val)
+
+/**
+ *	Holds DMA physical and virtual memory addresses
+ *	and length. This is used for making IOC calls.
+ */
+struct bna_meminfo {
+	u8 *kva;	/* Kernel virtual address */
+	u64 dma;	/* Actual physical address */
+	u32 len;	/* Memory size in bytes */
+};
+
+enum bna_dma_mem_type {
+	BNA_DMA_MEM_T_DIAG = 0,
+	BNA_DMA_MEM_T_FLASH = 1,
+	BNA_DMA_MEM_T_ATTR = 2,
+	BNA_KVA_MEM_T_FWTRC = 3,
+	BNA_MEM_T_MAX,
+};
+
+
+
+
+/**
+ * bna_register_callback()
+ *
+ *  Function called by the driver to register a callback with
+ *  the BNA
+ *
+ * @param[in] dev    - Opaque handle to BNA private device.
+ * @param[in] cbfns  - Structure of callbacks from drivers.
+ * @param[in] cbarg  - Argument to use with the callback.
+ *
+ * @return    BNA_OK or BNA_FAIL
+ */
+void bna_register_callback(struct bna_dev_s *dev, struct bna_mbox_cbfn *cbfns,
+	void *cbarg);
+
+/* Port Management */
+
+struct bna_port_stats {
+	u64 rx_frame_64;
+	u64 rx_frame_65_127;
+	u64 rx_frame_128_255;
+	u64 rx_frame_256_511;
+	u64 rx_frame_512_1023;
+	u64 rx_frame_1024_1518;
+	u64 rx_frame_1518_1522;
+	u64 rx_bytes;
+	u64 rx_packets;
+	u64 rx_fcs_error;
+	u64 rx_multicast;
+	u64 rx_broadcast;
+	u64 rx_control_frames;
+	u64 rx_pause;
+	u64 rx_unknown_opcode;
+	u64 rx_alignment_error;
+	u64 rx_frame_length_error;
+	u64 rx_code_error;
+	u64 rx_carrier_sense_error;
+	u64 rx_undersize;
+	u64 rx_oversize;
+	u64 rx_fragments;
+	u64 rx_jabber;
+	u64 rx_drop;
+
+	u64 tx_bytes;
+	u64 tx_packets;
+	u64 tx_multicast;
+	u64 tx_broadcast;
+	u64 tx_pause;
+	u64 tx_deferral;
+	u64 tx_excessive_deferral;
+	u64 tx_single_collision;
+	u64 tx_muliple_collision;
+	u64 tx_late_collision;
+	u64 tx_excessive_collision;
+	u64 tx_total_collision;
+	u64 tx_pause_honored;
+	u64 tx_drop;
+	u64 tx_jabber;
+	u64 tx_fcs_error;
+	u64 tx_control_frame;
+	u64 tx_oversize;
+	u64 tx_undersize;
+	u64 tx_fragments;
+};
+
+
+#define BNA_LINK_SPEED_10Gbps	10000
+struct bna_port_param {
+	u32 supported; /* Speeds and Flow Control supported */
+	u32 advertising;   /* speeds and Flow-Control advertised */
+	u32 speed;
+	u32 duplex;
+	u32 autoneg;
+	u32 port;
+};
+
+/**
+ * bna_port_param_get()
+ *
+ *   Get the port parameters.
+ *
+ * @param[in]   dev		- pointer to BNA device structure
+ * @param[out]  param_ptr	- pointer to where the parameters will be
+ *       			  returned.
+ * @return void
+ */
+void bna_port_param_get(struct bna_dev_s *dev,
+	 struct bna_port_param *param_ptr);
+
+
+/**
+ * bna_port_mac_get()
+ *
+ *   Get the Burnt-in or permanent MAC address.  This function does not return
+ *   the MAC set thru bna_rxf_ucast_mac_set() but the one that is assigned to
+ *   the port upon reset.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[out] mac_ptr - Burnt-in or permanent MAC address.
+ *
+ * @return void
+ */
+void bna_port_mac_get(struct bna_dev_s *dev, u8 *mac_ptr);
+
+
+/**
+ * bna_port_admin()
+ *
+ *   Enable (up) or disable (down) the interface administratively.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  enable - enable/disable the interface.
+ *
+ * @return void
+ */
+enum bna_status_e bna_port_admin(struct bna_dev_s *dev,
+	enum bna_enable_e enable);
+
+
+/**
+ * bna_port_stats_get()
+ *
+ *   Get the port statistics.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure
+ * @param[out]  stats_ptr - pointer to where the statistics will be returned.
+ *
+ * @return void
+ */
+void bna_port_stats_get(void *dev, struct bna_port_stats *stats_ptr);
+
+/**
+ * Ethernet 802.3X PAUSE confiiguration
+ */
+struct bna_pause_config {
+	u8		tx_pause;
+	u8		rx_pause;
+};
+
+/**
+ * bna_set_pause_config()
+ *
+ *   Enable/disable Tx/Rx pause through F/W
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure
+ * @param[in]   pause 	  - pointer to struct bna_pause_config
+ * @param[in]   cbarg	  - argument for the callback function
+ *
+ * @return BNA_OK in case of success BNA_FAIL otherwise.
+ */
+enum bna_status_e bna_set_pause_config(struct bna_dev_s *dev,
+	struct bna_pause_config *pause, void *cbarg);
+
+/**
+ * bna_mtu_info()
+ *
+ *   Send MTU information to F/W.
+ *   This is required to do PAUSE efficiently.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure
+ * @param[in]   mtu	  - current mtu size
+ * @param[in]   cbarg	  - argument for the callback function
+ *
+ * @return BNA_OK in case of success BNA_FAIL otherwise.
+ */
+enum bna_status_e bna_mtu_info(struct bna_dev_s *dev, u16 mtu, void *cbarg);
+
+/*
+ *
+ *
+ *   D O O R B E L L   D E F I N E S
+ *
+ *
+ */
+
+/**
+ * These macros build the data portion of the TxQ/RxQ doorbell.
+ */
+#define BNA_DOORBELL_Q_PRD_IDX(_producer_index) (0x80000000 | (_producer_index))
+#define BNA_DOORBELL_Q_STOP			(0x40000000)
+
+/* These macros build the data portion of the IB doorbell. */
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
+				(0x80000000 | ((_timeout) << 16) | (_events))
+#define BNA_DOORBELL_IB_INT_DISABLE 		(0x40000000)
+
+
+/*
+ *
+ *
+ *   I N T E R R U P T   B L O C K   D E F I N E S
+ *
+ *
+ */
+
+/* IB Structure */
+struct bna_ib {
+	void __iomem *doorbell_addr;	/* PCI address for IB doorbell */
+	u32 doorbell_ack;		/* ack data format except for #
+					of events */
+};
+
+
+/* IB Control Flags in IB Configuration */
+typedef u8 bna_ib_cf_t;
+
+#define BNA_IB_CF_RESERVED1 		(1 << 7)
+#define BNA_IB_CF_ACK_PENDING		(1 << 6)	/* Read Only */
+#define BNA_IB_CF_INTER_PKT_DMA		(1 << 5)	/* DMA segment w/o
+							   issuing interrupt */
+#define BNA_IB_CF_INT_ENABLE		(1 << 4)	/* Interrupt enable */
+#define BNA_IB_CF_INTER_PKT_ENABLE	(1 << 3)	/* Inter Packet
+							   Mechanism enable */
+#define BNA_IB_CF_COALESCING_MODE	(1 << 2)	/* 1 = Continuous Mode;
+							   0 = One-shot */
+#define BNA_IB_CF_MSIX_MODE		(1 << 1)	/* 1 = MSIX mode;
+							    0 = INTx mode */
+#define BNA_IB_CF_MASTER_ENABLE		(1 << 0)	/* Master Enable */
+
+
+/* IB Configuration Structure */
+struct bna_ib_config {
+	struct bna_dma_addr	ib_seg_addr;	/* Host Address of IB Segment */
+	u8			coalescing_timer;
+	bna_ib_cf_t		control_flags;
+	u8			msix_vector;
+	u8			interpkt_count;
+	u8			interpkt_timer;
+	u8			seg_size;	/* No. of entries */
+	u8			index_table_offset;
+};
+
+
+/*
+ * bna_ib_idx_reset()
+ *
+ *   For the specified IB, it clears the IB index
+ *
+ * @param[in] cfg_ptr - pointer to IB Configuration Structure.
+ *
+ * @return none
+ */
+void
+bna_ib_idx_reset(struct bna_dev_s *dev, const struct bna_ib_config *cfg_ptr);
+
+/**
+ * bna_ib_config_set()
+ *
+ *   For IB "ib_id", it configures the Interrupt Block specified by "cfg_ptr".
+ *
+ * @param[in] ib_ptr  - pointer to IB Data Structure.
+ * @param[in] ib_id   - interrupt-block ID
+ * @param[in] cfg_ptr - pointer to IB Configuration Structure.
+ *
+ * @return None
+ */
+void bna_ib_config_set(struct bna_dev_s *bna_dev, struct bna_ib *ib_ptr,
+	unsigned int ib_id, const struct bna_ib_config *cfg_ptr);
+
+
+/**
+ * bna_ib_ack()
+ *
+ *   Acknowledges the number of events triggered by the current interrupt.
+ *
+ * @param[in] bna_dev   - Opaque handle to bna device.
+ * @param[in] ib_ptr	- pointer to IB Data Structure.
+ * @param[in] events	- number of events to acknowledge.
+ *
+ * @return None
+ */
+static inline void bna_ib_ack(struct bna_dev_s *bna_dev,
+	const struct bna_ib *ib_ptr, u16 events) {
+	/*
+	 * bna_os_reg_write is defined in a header
+	 * included later
+	 */
+	bna_os_reg_write(ib_ptr->doorbell_addr,
+		(ib_ptr->doorbell_ack | events));
+}
+
+
+/**
+ * bna_ib_coalescing_timer_set()
+ *
+ *   Sets the timeout value in the coalescing timer
+ *
+ * @param[in] ib_ptr  - pointer to IB Data Structure.
+ * @param[in] timeout - coalescing timer value.
+ *
+ * @return None
+ */
+static inline void
+bna_ib_coalescing_timer_set(struct bna_dev_s *dev,
+    struct bna_ib *ib_ptr, u8 cls_timer) {
+	ib_ptr->doorbell_ack = BNA_DOORBELL_IB_INT_ACK(cls_timer, 0);
+}
+
+
+
+/**
+ * bna_ib_disable()
+ *
+ *   Disables the Interrupt Block "ib_id".
+ *
+ * @param[in] bna_dev - pointer to BNA private handle.
+ * @param[in] ib_ptr  - pointer to IB Data Structure.
+ *
+ * @return None
+ */
+void bna_ib_disable(struct bna_dev_s *bna_dev, const struct bna_ib *ib_ptr);
+
+
+/**
+ * Interrupt status register, mailbox status bits
+ */
+#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000
+#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000
+#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000
+#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000
+
+#define __LPU02HOST_MBOX0_MASK_BITS	0x00100000
+#define __LPU12HOST_MBOX0_MASK_BITS	0x00200000
+#define __LPU02HOST_MBOX1_MASK_BITS	0x00400000
+#define __LPU12HOST_MBOX1_MASK_BITS	0x00800000
+
+#define __LPU2HOST_MBOX_MASK_BITS			 \
+	(__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS |	\
+	  __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS)
+
+#define __LPU2HOST_IB_STATUS_BITS	0x0000ffff
+
+#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \
+	((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \
+			__LPU02HOST_MBOX1_STATUS_BITS))
+
+#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \
+	((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \
+		__LPU12HOST_MBOX1_STATUS_BITS))
+
+/**
+ * BNA_IS_MBOX_INTR()
+ *
+ *  Checks if the mailbox interrupt status bits
+ *  are set
+ *
+ * @param[in] _intr_status - Interrupt Status Register
+ */
+#define BNA_IS_MBOX_INTR(_intr_status)		\
+	((_intr_status) &  			\
+	(__LPU02HOST_MBOX0_STATUS_BITS |	\
+	 __LPU02HOST_MBOX1_STATUS_BITS |	\
+	 __LPU12HOST_MBOX0_STATUS_BITS |	\
+	 __LPU12HOST_MBOX1_STATUS_BITS))
+
+#define __EMC_ERROR_STATUS_BITS		0x00010000
+#define __LPU0_ERROR_STATUS_BITS	0x00020000
+#define __LPU1_ERROR_STATUS_BITS	0x00040000
+#define __PSS_ERROR_STATUS_BITS		0x00080000
+
+#define __HALT_STATUS_BITS		0x01000000
+
+#define __EMC_ERROR_MASK_BITS		0x00010000
+#define __LPU0_ERROR_MASK_BITS		0x00020000
+#define __LPU1_ERROR_MASK_BITS		0x00040000
+#define __PSS_ERROR_MASK_BITS		0x00080000
+
+#define __HALT_MASK_BITS		0x01000000
+
+#define __ERROR_MASK_BITS		\
+	(__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \
+	  __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \
+	  __HALT_MASK_BITS)
+
+/**
+ * BNA_IS_ERR_INTR()
+ *
+ *  Checks if the error interrupt status bits
+ *  are set
+ *
+ * @param[in] _intr_status - Interrupt Status Register
+ */
+#define BNA_IS_ERR_INTR(_intr_status)	\
+	((_intr_status) &  		\
+	(__EMC_ERROR_STATUS_BITS |  	\
+	 __LPU0_ERROR_STATUS_BITS | 	\
+	 __LPU1_ERROR_STATUS_BITS | 	\
+	 __PSS_ERROR_STATUS_BITS  | 	\
+	 __HALT_STATUS_BITS))
+
+/**
+ * BNA_IS_MBOX_ERR_INTR()
+ *
+ *  Checks if the mailbox and error interrupt status bits
+ *  are set
+ *
+ * @param[in] _intr_status - Interrupt Status Register
+ */
+#define BNA_IS_MBOX_ERR_INTR(_intr_status)	\
+	(BNA_IS_MBOX_INTR((_intr_status)) |	\
+	 BNA_IS_ERR_INTR((_intr_status)))	\
+
+/**
+ * BNA_IS_INTX_DATA_INTR()
+ *
+ *  Checks if the data bits (low 16 bits)
+ *  are set in case of INTx
+ *
+ * @param[in] _intr_status - Interrupt Status Register
+ */
+#define BNA_IS_INTX_DATA_INTR(_intr_status)	\
+	((_intr_status) & __LPU2HOST_IB_STATUS_BITS)
+
+/**
+ * BNA_INTR_STATUS_MBOX_CLR()
+ *
+ *  Clears the mailbox bits in _intr_status
+ *  Does not write to hardware
+ *
+ * @param[in] _intr_status - Interrupt Status Register
+ */
+#define BNA_INTR_STATUS_MBOX_CLR(_intr_status)			\
+do {								\
+	(_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS |	\
+			__LPU02HOST_MBOX1_STATUS_BITS | 	\
+			__LPU12HOST_MBOX0_STATUS_BITS | 	\
+			__LPU12HOST_MBOX1_STATUS_BITS);      \
+} while (0)
+
+/**
+ * BNA_INTR_STATUS_ERR_CLR()
+ *
+ *  Clears the error bits in _intr_status
+ *  Does not write to hardware
+ *
+ * @param[in] _intr_status - Interrupt Status Register
+ */
+#define BNA_INTR_STATUS_ERR_CLR(_intr_status)		\
+do {							\
+	(_intr_status) &= ~(__EMC_ERROR_STATUS_BITS |	\
+		__LPU0_ERROR_STATUS_BITS |		\
+		__LPU1_ERROR_STATUS_BITS |		\
+		__PSS_ERROR_STATUS_BITS  |		\
+		__HALT_STATUS_BITS);      \
+} while (0)
+
+
+/**
+ * bna_mbox_err_handler()
+ *
+ *    The driver calls this API back after processing the
+ *    mailbox/error interrupt for MSIX and INTx types.
+ *    Should be called with a lock held.
+ *    This will do the following for mbox interrupt :
+ *  1) Read the contents of the mbox
+ *  	2) Call a function registered by the OS driver to handle
+ *     the mailbox command.
+ *  3) Queue the next mbox command
+ *    This will do the following for error interrupt :
+ *  1) Interpret the type of error & call the
+ *     right BNA handler.
+ *  2) Call the driver defined callback.
+ *
+ * @param[in] bna_dev   - Pointer to BNA private handle.
+ * @param[in] status	- Interrupt status register.
+ *
+ * @return void
+ */
+void bna_mbox_err_handler(struct bna_dev_s *bna_dev, u32 status);
+
+/**
+ * bna_mbox_send()
+ *
+ *    The driver calls this API to send a command to the
+ *    firmware
+ *
+ * @param[in] bna_dev   - Pointer to BNA private handle.
+ * @param[in] cmd   	- pointer to the command structur
+ * @param[in] cmd_len   - length of the command structure
+ *
+ * @return BNA_OK or BNA_FAIL
+ */
+enum bna_status_e bna_mbox_send(struct bna_dev_s *bna_dev, void *cmd,
+	u32 cmd_len, void *cbarg);
+
+
+
+/*******************************************************************/
+/*
+ *
+ *
+ *   Q U E U E   D E F I N E S
+ *
+ *
+ */
+#define BNA_TXQ_ENTRY_SIZE	64  /* bytes */
+#define BNA_RXQ_ENTRY_SIZE	8   /* bytes */
+#define BNA_CQ_ENTRY_SIZE	16  /* bytes */
+/**
+ *  Queue Page Table (QPT)
+ */
+struct bna_qpt {				/* Queue Page Table */
+	struct bna_dma_addr	hw_qpt_ptr;	/* Pointer to QPT used by HW */
+	void *kv_qpt_ptr;	/* Kernel virtual pointer to
+						   hw QPT */
+	void			**qpt_ptr;	/* Pointer to S/W QPT for page
+						   segmented Q's */
+	u16		page_count;	/* Size of QPT (i.e., number of
+						   pages) */
+	u16		page_size;	/* Size of each page */
+};
+
+#define BNA_QPT_SIZE(_queue_size, _page_size)	\
+			(((_queue_size) + (_page_size) - 1)/(_page_size))
+
+struct bna_q {
+	u16	producer_index;
+	u16	consumer_index;
+	u32	q_depth;	/* Depth of the q */
+	void		**qpt_ptr;	/* pointer to SW QPT for Page-segmented
+					   queue */
+};
+
+
+/**
+ * BNA_TXQ_QPGE_PTR_GET()
+ *
+ *   Gets the pointer corresponding to an queue-entry index for a
+ *   page-segmented queue.
+ *
+ *   NOTE:  _q_depth, sizeof(_cast) and BNA_PAGE_SIZE must be power of two.
+ *  		_q_depth * sizeof(_cast) must be multiple of a BNA_PAGE_SIZE.
+ *
+ * @param[in]  _qe_idx  	 - producer/consumer queue entry index
+ * @param[in]  _q_ptr   	 - pointer to page-segmented queue structure
+ * @param[out] _qe_ptr  	 - producer/consumer queue-entry pointer
+ * @param[out] _qe_ptr_range	 - number of entries addressable by
+ *                                 queue-entry pointer (warns going beyond the
+ *                                 page-size)
+ */
+/* TxQ element is 64 bytes */
+#define BNA_TXQ_PAGE_INDEX_MAX (BNA_PAGE_SIZE >> 6)
+#define BNA_TXQ_PAGE_INDEX_MAX_SHIFT (BNA_PAGE_SHIFT - 6)
+
+#define BNA_TXQ_QPGE_PTR_GET(_qe_idx, _q_ptr, _qe_ptr, _qe_ptr_range) \
+{ \
+      unsigned int page_index;        /* index within a page */ \
+      void *page_addr; \
+      \
+      page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1);      \
+      (_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index);      \
+      page_addr = \
+	(_q_ptr)->qpt_ptr[((_qe_idx) >> BNA_TXQ_PAGE_INDEX_MAX_SHIFT)]; \
+      (_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \
+}
+
+/**
+ * BNA_RXQ_QPGE_PTR_GET()
+ *
+ *   Gets the pointer corresponding to an queue-entry index for a
+ *   page-segmented queue.
+ *
+ *   NOTE:  _q_depth, sizeof(_cast) and BNA_PAGE_SIZE must be power of two.
+ *  		_q_depth * sizeof(_cast) must be multiple of a BNA_PAGE_SIZE.
+ *
+ * @param[in]  _qe_idx  	 - producer/consumer queue entry index
+ * @param[in]  _q_ptr   	 - pointer to page-segmented queue structure
+ * @param[out] _qe_ptr  	 - producer/consumer queue-entry pointer
+ * @param[out] _qe_ptr_range	 - number of entries addressable by
+ *                                 queue-entry pointer (warns going beyond the
+ *                                 page-size)
+ */
+#define BNA_RXQ_PAGE_INDEX_MAX (BNA_PAGE_SIZE >> 3) /* RxQ element is 8 bytes */
+#define BNA_RXQ_PAGE_INDEX_MAX_SHIFT (BNA_PAGE_SHIFT - 3)
+
+#define BNA_RXQ_QPGE_PTR_GET(_qe_idx, _q_ptr, _qe_ptr, _qe_ptr_range) \
+{ \
+      unsigned int page_index;        /* index within a page */ \
+      void *page_addr; \
+      \
+      page_index = (_qe_idx) & (BNA_RXQ_PAGE_INDEX_MAX - 1);      \
+      (_qe_ptr_range) = (BNA_RXQ_PAGE_INDEX_MAX - page_index);      \
+      page_addr = \
+	(_q_ptr)->qpt_ptr[((_qe_idx) >> BNA_RXQ_PAGE_INDEX_MAX_SHIFT)]; \
+      (_qe_ptr) = &((struct bna_rxq_entry *)(page_addr))[page_index]; \
+}
+
+/**
+ * BNA_CQ_QPGE_PTR_GET()
+ *
+ *   Gets the pointer corresponding to an queue-entry index for a
+ *   page-segmented queue.
+ *
+ *   NOTE:  _q_depth, sizeof(_cast) and BNA_PAGE_SIZE must be power of two.
+ *  		_q_depth * sizeof(_cast) must be multiple of a BNA_PAGE_SIZE.
+ *
+ * @param[in]  _qe_idx  	 - producer/consumer queue entry index
+ * @param[in]  _q_ptr   	 - pointer to page-segmented queue structure
+ * @param[out] _qe_ptr  	 - producer/consumer queue-entry pointer
+ * @param[out] _qe_ptr_range	 - number of entries addressable by
+ *                                 queue-entry pointer (warns going beyond the
+ *                                 page-size)
+ */
+#define BNA_CQ_PAGE_INDEX_MAX (BNA_PAGE_SIZE >> 4) /* CQ element is 16 bytes */
+#define BNA_CQ_PAGE_INDEX_MAX_SHIFT (BNA_PAGE_SHIFT - 4)
+
+#define BNA_CQ_QPGE_PTR_GET(_qe_idx, _q_ptr, _qe_ptr, _qe_ptr_range) \
+{ \
+      unsigned int page_index;        /* index within a page */ \
+      void *page_addr; \
+      \
+      page_index = (_qe_idx) & (BNA_CQ_PAGE_INDEX_MAX - 1);      \
+      (_qe_ptr_range) = (BNA_CQ_PAGE_INDEX_MAX - page_index);      \
+      page_addr = \
+	(_q_ptr)->qpt_ptr[((_qe_idx) >> BNA_CQ_PAGE_INDEX_MAX_SHIFT)]; \
+      (_qe_ptr) = &((struct bna_cq_entry *)(page_addr))[page_index]; \
+}
+
+/**
+ * BNA_QE_INDX_2_PTR()
+ *
+ *   Gets the pointer corresponding to an queue-entry index for a virtually-
+ *   contiguous queue.
+ *
+ *   NOTE:  _q_depth must be power of two.
+ *
+ * @param[in]  _cast		 - type cast of the entry.
+ * @param[in]  _qe_idx  	 - producer/consumer queue entry index
+ * @param[in]  _q_base  	 - queue base address
+ */
+#define BNA_QE_INDX_2_PTR(_cast, _qe_idx, _q_base) \
+	(&((_cast *)(_q_base))[(_qe_idx)])
+
+
+/**
+ * BNA_QE_INDX_RANGE()
+ *
+ *   Returns number of entries that can be consecutively addressed for the
+ *   specified queue.  This function indicates when BNA_QE_INDX_2_PTR() must
+ *   be called again get a new pointer due to the effect of wrapping around
+ *   the queue.
+ *
+ *   NOTE:  _q_depth must be power of two.
+ *
+ * @param[in]  _qe_idx  	 - producer/consumer queue entry index
+ * @param[in]  _q_depth 	 - queue size in number of entries
+ */
+#define BNA_QE_INDX_RANGE(_qe_idx, _q_depth) \
+	((_q_depth) - (_qe_idx))
+
+
+/**
+ * BNA_QE_INDX_ADD()
+ *
+ *   Adds to a producer or consumer queue-entry index for either
+ *   virtually-contiguous or page-segmented queue.
+ *
+ *   NOTE:  _q_depth must power of two.
+ *
+ * @param[in]  _qe_idx  - producer/consumer queue entry index
+ * @param[out] _qe_idx  - updated producer/consumer queue entry index
+ * @param[in]  _q_depth - queue size in number of entries
+ */
+#define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth) \
+	((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1))
+
+
+/**
+ * BNA_QE_FREE_CNT
+ *
+ *   Returns the number of entries that can be added into the queue.
+ *
+ *   NOTE:  Must reserved one entry to distinguish between an empty
+ *  		and a full queue.
+ *
+ * @param[in]  _q_ptr   - pointer to queue structure
+ * @param[in]  _q_depth - queue size in number of entries
+ */
+#define BNA_QE_FREE_CNT(_q_ptr, _q_depth) \
+  (((_q_ptr)->consumer_index - (_q_ptr)->producer_index - 1) & ((_q_depth) - 1))
+
+/**
+ * BNA_QE_IN_USE_CNT
+ *
+ *    Returns the number of entries in the queue.
+ *
+ * @param[in]  _q_ptr   - pointer to queue structure
+ * @param[in]  _q_depth - queue size in number of entries
+ */
+#define BNA_QE_IN_USE_CNT(_q_ptr, _q_depth) \
+   ((((_q_ptr)->producer_index - (_q_ptr)->consumer_index)) & (_q_depth - 1))
+
+
+/**
+ * BNA_Q_GET_CI
+ *
+ *    Returns the current consumer index for that queue.
+ *
+ * @param[in]  _q_ptr   - pointer to queue (Tx/Rx/C) structure
+ */
+#define BNA_Q_GET_CI(_q_ptr)   \
+	((_q_ptr)->q.consumer_index)
+
+/**
+ * BNA_Q_GET_PI
+ *
+ *    Returns the current producer index for that queue.
+ *
+ * @param[in]  _q_ptr   - pointer to queue (Tx/Rx/C) structure
+ */
+#define BNA_Q_GET_PI(_q_ptr)   \
+	((_q_ptr)->q.producer_index)
+
+/**
+ * BNA_Q_PI_ADD
+ *
+ *   Increments the producer index of the queue by a certain number
+ *
+ * @param[in]  _q_ptr   - pointer to queue (Tx/Rx/C) structure
+ * @param[in]  _num 	- the number by which CI needs to be incremented
+ */
+#define BNA_Q_PI_ADD(_q_ptr, _num) 		\
+	(_q_ptr)->q.producer_index =			\
+		(((_q_ptr)->q.producer_index + (_num))  \
+		& ((_q_ptr)->q.q_depth - 1))
+
+/**
+ * BNA_Q_CI_ADD
+ *
+ *   Increments the consumer index of the queue by a certain number
+ *
+ * @param[in]  _q_ptr   - pointer to queue (Tx/Rx/C) structure
+ * @param[in]  _num 	- the number by which CI needs to be incremented
+ */
+#define BNA_Q_CI_ADD(_q_ptr, _num) 		\
+	(_q_ptr)->q.consumer_index =			\
+		(((_q_ptr)->q.consumer_index + (_num))  \
+		& ((_q_ptr)->q.q_depth - 1))
+
+/**
+ * BNA_Q_FREE_COUNT()
+ *
+ *  Returns the number of free entries for TxQ/RxQ/CQ
+ *
+ * @param[in] _q_ptr	- pointer to TxQ/RxQ/CQ
+ */
+#define BNA_Q_FREE_COUNT(_q_ptr)			\
+	(BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth))
+
+/**
+ * BNA_Q_FREE_COUNT()
+ *
+ *  Returns the number of entries in use for the queue.
+ *
+ * @param[in] _q_ptr	- pointer to TxQ/RxQ/CQ
+ */
+#define BNA_Q_IN_USE_COUNT(_q_ptr)  		\
+	(BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
+/*
+ *
+ *
+ *   T X   Q U E U E   D E F I N E S
+ *
+ *
+ */
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+struct bna_txq_wi_vector {  /* Tx Buffer Descriptor */
+	u16		reserved;
+	u16		length; 	/* Only 14 LSB are valid */
+	struct bna_dma_addr  host_addr; 	/* Tx-Buffer DMA address */
+};
+
+
+/* TxQ Entry Opcodes */
+#define BNA_TXQ_WI_SEND 		(0x402)	/* Single Frame Transmission */
+#define BNA_TXQ_WI_SEND_LSO 		(0x403)	/* Multi-Frame Transmission */
+#define BNA_TXQ_WI_EXTENSION		(0x104)	/* Extension WI */
+typedef u16 bna_txq_wi_opcode_t;
+
+
+/* TxQ Entry Control Flags */
+#define BNA_TXQ_WI_CF_FCOE_CRC  	(1 << 8)
+#define BNA_TXQ_WI_CF_IPID_MODE 	(1 << 5)
+#define BNA_TXQ_WI_CF_INS_PRIO  	(1 << 4)
+#define BNA_TXQ_WI_CF_INS_VLAN  	(1 << 3)
+#define BNA_TXQ_WI_CF_UDP_CKSUM 	(1 << 2)
+#define BNA_TXQ_WI_CF_TCP_CKSUM 	(1 << 1)
+#define BNA_TXQ_WI_CF_IP_CKSUM  	(1 << 0)
+typedef u16 bna_txq_wi_ctrl_flag_t;
+
+
+/**
+ *  TxQ Entry Structure
+ *
+ *  BEWARE:  Load values into this structure with correct endianess.
+ */
+struct bna_txq_entry {
+	union {
+		struct {
+			u8 reserved;
+			u8 num_vectors;	/* number of vectors present */
+			bna_txq_wi_opcode_t opcode; /* Either BNA_TXQ_WI_SEND or
+						BNA_TXQ_WI_SEND_LSO */
+			bna_txq_wi_ctrl_flag_t  flags;	/* OR of all the flags*/
+			u16	l4_hdr_size_n_offset;
+			u16	vlan_tag;
+			u16	lso_mss; /* Only 14 LSB are valid */
+			u32	frame_length; /* Only 24 LSB are valid*/
+		} wi;
+
+		struct {
+			u16	reserved;
+			bna_txq_wi_opcode_t 	opcode;/* Must be
+						BNA_TXQ_WI_EXTENSION */
+			u32	reserved2[3]; /* Place holder for
+					    removed vector (12 bytes) */
+		} wi_ext;
+	} hdr;
+	struct bna_txq_wi_vector vector[4];
+};
+#define wi_hdr  	hdr.wi
+#define wi_ext_hdr  hdr.wi_ext
+
+#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+		(((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/* TxQ Structure */
+struct bna_txq {
+	u32	*doorbell;
+	struct		bna_q q;
+};
+
+
+/* TxQ Configuration */
+struct bna_txq_config {
+	struct bna_qpt qpt;
+	u16	ib_id;
+	u8 	ib_seg_index;	/* index into IB segment */
+	u8 	txf_id;		/* Tx-Function ID */
+	u8 	priority;	/* frame or scheduling priority? FIXME*/
+	u16	wrr_quota;	/* Weighted Round-Robin Quota */
+};
+
+
+/**
+ * bna_txq_config()
+ *
+ * For TxQ "txq_id", it configures the Tx-Queue as specified by "cfg_ptr".
+ */
+void bna_txq_config(struct bna_dev_s *dev, struct bna_txq *q_ptr,
+		unsigned int txq_id, const struct bna_txq_config *cfg_ptr);
+
+
+
+/**
+ * bna_txq_pg_prod_ptr()
+ *
+ * Returns the producer pointer and its range for the specified page-segmented
+ * queue.
+ */
+static inline struct bna_txq_entry
+	*bna_txq_pg_prod_ptr(const struct bna_txq *q_ptr,
+			      unsigned int *ptr_range) {
+	struct bna_txq_entry *qe_ptr;
+
+	BNA_TXQ_QPGE_PTR_GET(q_ptr->q.producer_index,
+			  &q_ptr->q, qe_ptr, *ptr_range);
+	return qe_ptr;
+}
+
+/**
+ * bna_txq_prod_indx_doorbell()
+ *
+ * Informs Catapult ASIC about queued entries.
+ */
+static inline void bna_txq_prod_indx_doorbell(const struct bna_txq *q_ptr)
+{
+	bna_os_reg_write(q_ptr->doorbell,
+			 BNA_DOORBELL_Q_PRD_IDX(q_ptr->q.producer_index));
+}
+
+
+/**
+ * bna_txq_pg_cons_ptr()
+ *
+ * Returns the consumer pointer and its range for the specified
+ * page-segmented
+ * queue.
+ */
+static inline struct bna_txq_entry
+*bna_txq_pg_cons_ptr(const struct bna_txq *q_ptr, unsigned int *ptr_range) {
+	struct bna_txq_entry *qe_ptr;
+
+	BNA_TXQ_QPGE_PTR_GET(q_ptr->q.consumer_index,
+			  &q_ptr->q, qe_ptr, *ptr_range);
+	return qe_ptr;
+}
+
+/**
+ * bna_txq_stop()
+ *
+ * 	Stops the RxQ identified by the RxQ Id.
+ *  	Should be called with a lock held
+ *	The driver should wait for the response to
+ *	know if the Q stop is successful or not.
+ *
+ * @param[in] q_id	- Id of the TxQ
+ *
+ * @return    BNA_OK in case of success, else BNA_FAIL
+ */
+enum bna_status_e bna_txq_stop(struct bna_dev_s *bna_dev, u32 txq_id);
+
+/*
+ *
+ *
+ *   R X   Q U E U E   D E F I N E S
+ *
+ *
+ */
+/* RxQ Entry (Rx-Vector, Rx-Buffer Address) */
+struct bna_rxq_entry {	/* Rx-Buffer */
+	struct bna_dma_addr  host_addr; 	 /* Rx-Buffer DMA address */
+};
+
+
+/* RxQ Structure */
+struct bna_rxq {
+	u32	*doorbell;
+	struct bna_q   q;
+};
+
+
+/* RxQ Configuration */
+struct bna_rxq_config {
+	struct bna_qpt   qpt;
+	u8 	cq_id;  		/* Completion Queue ID */
+	u16	buffer_size;	/* Rx-Buffer Length */
+};
+
+/**
+ *  bna_rxq_config()
+ *
+ *  For RxQ "rxq_id", it configures the Rx-Queue as specified by "cfg_ptr".
+ */
+void bna_rxq_config(struct bna_dev_s *dev, struct bna_rxq *q_ptr,
+		unsigned int rxq_id, const struct bna_rxq_config *cfg_ptr);
+
+/**
+ * bna_rxq_pg_prod_ptr()
+ *
+ * Returns the producer pointer and its range for the specified
+ * page-segmented
+ * queue.
+ */
+static inline struct bna_rxq_entry
+*bna_rxq_pg_prod_ptr(const struct bna_rxq *q_ptr, unsigned int *ptr_range) {
+	struct bna_rxq_entry *qe_ptr;
+
+	BNA_RXQ_QPGE_PTR_GET(q_ptr->q.producer_index,
+			  &q_ptr->q, qe_ptr, *ptr_range);
+	return qe_ptr;
+}
+/**
+ * bna_rxq_pg_cons_ptr()
+ *
+ * Returns the consumer pointer and its range for the specified
+ * page-segmented
+ * queue.
+ */
+static inline struct bna_rxq_entry
+*bna_rxq_pg_cons_ptr(const struct bna_rxq *q_ptr, unsigned int *ptr_range) {
+	struct  bna_rxq_entry *qe_ptr;
+
+	BNA_RXQ_QPGE_PTR_GET(q_ptr->q.consumer_index,
+			  &q_ptr->q, qe_ptr, *ptr_range);
+	return qe_ptr;
+}
+
+/**
+ * bna_rxq_prod_indx_doorbell()
+ *
+ * Informs Catapult ASIC about queued entries.
+ */
+static inline void bna_rxq_prod_indx_doorbell(const struct bna_rxq *q_ptr)
+{
+	bna_os_reg_write(q_ptr->doorbell,
+		BNA_DOORBELL_Q_PRD_IDX(q_ptr->q.producer_index));
+}
+
+
+/**
+ * bna_rxq_stop()
+ *
+ * 	Stops the RxQ identified by the RxQ Id.
+ *	Should be called with a lock held
+ *	The driver should wait for the response to
+ *	know if the Q stop is successful or not.
+ *
+ * @param[in] q_id	- Id of the RxQ
+ *
+ * @return    BNA_OK in case of success, else BNA_FAIL
+ */
+enum bna_status_e bna_rxq_stop(struct bna_dev_s *bna_dev, u32 rxq_id);
+
+/**
+ * bna_multi_rxq_stop()
+ *
+ * 	Stops the set of RxQs identified by rxq_id_mask
+ *	Should be called with a lock held
+ *	The driver should wait for the response to
+ *	know if the Q stop is successful or not.
+ *
+ * @param[in] q_id	- Id of the RxQ
+ *
+ * @return    BNA_OK in case of success, else BNA_FAIL
+ */
+enum bna_status_e bna_multi_rxq_stop(struct bna_dev_s *dev, u64 rxq_id_mask);
+/*
+ *
+ *
+ *   R X   C O M P L E T I O N   Q U E U E   D E F I N E S
+ *
+ *
+ */
+/* CQ Entry Flags */
+#define	BNA_CQ_EF_MAC_ERROR 	(1 <<  0)
+#define	BNA_CQ_EF_FCS_ERROR 	(1 <<  1)
+#define	BNA_CQ_EF_TOO_LONG  	(1 <<  2)
+#define	BNA_CQ_EF_FC_CRC_OK 	(1 <<  3)
+
+#define	BNA_CQ_EF_RSVD1 	(1 <<  4)
+#define	BNA_CQ_EF_L4_CKSUM_OK	(1 <<  5)
+#define	BNA_CQ_EF_L3_CKSUM_OK	(1 <<  6)
+#define	BNA_CQ_EF_HDS_HEADER	(1 <<  7)
+
+#define	BNA_CQ_EF_UDP   	(1 <<  8)
+#define	BNA_CQ_EF_TCP   	(1 <<  9)
+#define	BNA_CQ_EF_IP_OPTIONS	(1 << 10)
+#define	BNA_CQ_EF_IPV6  	(1 << 11)
+
+#define	BNA_CQ_EF_IPV4  	(1 << 12)
+#define	BNA_CQ_EF_VLAN  	(1 << 13)
+#define	BNA_CQ_EF_RSS   	(1 << 14)
+#define	BNA_CQ_EF_RSVD2 	(1 << 15)
+
+#define	BNA_CQ_EF_MCAST_MATCH   (1 << 16)
+#define	BNA_CQ_EF_MCAST 	(1 << 17)
+#define BNA_CQ_EF_BCAST 	(1 << 18)
+#define	BNA_CQ_EF_REMOTE 	(1 << 19)
+
+#define	BNA_CQ_EF_LOCAL		(1 << 20)
+typedef u32 bna_cq_e_flag_t;
+
+
+/* CQ Entry Structure */
+struct bna_cq_entry {
+	bna_cq_e_flag_t flags;
+	u16	vlan_tag;
+	u16	length;
+	u32	rss_hash;
+	u8 	valid;
+	u8 	reserved1;
+	u8 	reserved2;
+	u8 	rxq_id;
+};
+
+
+/* CQ Structure */
+struct bna_cq {
+	struct bna_q   q;
+};
+
+
+/* CQ Configuration */
+struct bna_cq_config {
+	struct bna_qpt	qpt;
+	u16	ib_id;
+	u8		ib_seg_index;   /* index into IB segment */
+};
+
+/**
+ *  bna_cq_config()
+ *
+ *  For CQ "cq_id", it configures the Rx-Completion Queue as specified by
+ *  "cfg_ptr".
+ */
+void bna_cq_config(struct bna_dev_s *dev, struct bna_cq *q_ptr,
+	unsigned int cq_id, const struct bna_cq_config *cfg_ptr);
+
+
+/**
+ * bna_cq_pg_prod_ptr()
+ *
+ * Returns the producer pointer and its range for the specified
+ * page-segmented
+ * queue.
+ */
+static inline struct bna_cq_entry
+*bna_cq_pg_prod_ptr(const struct bna_cq *q_ptr, unsigned int *ptr_range) {
+	struct bna_cq_entry *qe_ptr;
+
+	BNA_CQ_QPGE_PTR_GET(q_ptr->q.producer_index,
+			  &q_ptr->q, qe_ptr, *ptr_range);
+	return qe_ptr;
+}
+/**
+ * bna_cq_pg_cons_ptr()
+ *
+ * Returns the consumer pointer and its range for the specified
+ * page-segmented
+ * queue.
+ */
+static inline struct bna_cq_entry
+*bna_cq_pg_cons_ptr(const struct bna_cq *q_ptr, unsigned int *ptr_range) {
+	struct  bna_cq_entry *qe_ptr;
+
+	BNA_CQ_QPGE_PTR_GET(q_ptr->q.consumer_index,
+			  &q_ptr->q, qe_ptr, *ptr_range);
+	return qe_ptr;
+}
+/*
+ *
+ *
+ *   T X   F U N C T I O N   D E F I N E S
+ *
+ *
+ */
+
+/**
+ * TxF Control Flags
+ *
+ * BNA_TXF_CF_VLAN_INSERT & BNA_TXF_CF_VLAN_ADMIT are only applicable when
+ * BNA_TXF_CF_VLAN_WI_BASED == 0 (i.e., VLAN MODE = By Tx-Function).
+ */
+#define	BNA_TXF_CF_VSWITCH_UCAST	(1 << 15)
+#define	BNA_TXF_CF_VSWITCH_MCAST	(1 << 14)
+#define	BNA_TXF_CF_VLAN_WI_BASED	(1 << 13) /*  else Tx-Function Based */
+#define	BNA_TXF_CF_MAC_SA_CHECK 	(1 << 12)
+#define	BNA_TXF_CF_RSVD1		(1 << 11)
+#define	BNA_TXF_CF_VLAN_INSERT  (1 << 10) /*  Insert function's VLAN ID */
+#define	BNA_TXF_CF_VLAN_ADMIT   (1 <<  9) /*  process VLAN frames from Host */
+#define	BNA_TXF_CF_VLAN_FILTER  (1 <<  8) /*  check against Rx VLAN Table */
+#define	BNA_TXF_CF_RSVD2		(0x7F << 1)
+#define	BNA_TXF_CF_ENABLE   		(1 <<  0)
+typedef u16 bna_txf_ctrl_flag_t;
+
+
+/* TxF Configuration */
+struct bna_txf_config {
+	bna_txf_ctrl_flag_t flags; /* OR of bna_txf_ctrl_flag_t */
+	u16	vlan;	/* valid when BNA_TXF_CF_VLAN_WI_BASED == 0 */
+	u8 	rxf_id; /* validate BNA_TXF_CF_VSWITCH_UCAST */
+};
+
+/**
+ * bna_txf_config_set()
+ *
+ *   For TxF "txf_id", it configures the TxF specified by "cfg_ptr" and
+ *   indicates to the statistics collector to collect statistics for this
+ *   Tx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  txf_id  - tx-function ID.
+ * @param[in]  cfg_ptr - pointer to tx-function configuration.
+ *
+ * @return void
+ */
+void bna_txf_config_set(struct bna_dev_s *dev, unsigned int txf_id,
+     const struct bna_txf_config *cfg_ptr);
+
+
+/**
+ * bna_txf_config_clear()
+ *
+ *   For TxF "txf_id", it clears its configuration and indicates to the
+ *   statistics collector to stop collecting statistics for this
+ *   Tx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  txf_id  - tx-function ID.
+ *
+ * @return void
+ */
+void bna_txf_config_clear(struct bna_dev_s *dev, unsigned int txf_id);
+
+
+
+/**
+ * bna_txf_disable()
+ *
+ *  Disables the Tx Function without clearing the configuration
+ *  Also disables collection of statistics.
+ *
+ * @param[in] bna_dev   - Pointer to BNA BNA device handle
+ * @param[in] txf_id	- Id of the Tx Function to be disabled
+ *
+ * @return void
+ */
+void bna_txf_disable(struct bna_dev_s *bna_dev, unsigned int txf_id);
+
+/**
+ * bna_txf_enable()
+ *
+ *  Enables the Tx Function
+ *
+ * @param[in] bna_dev   - Pointer to BNA BNA device handle
+ * @param[in] txf_id	- Id of the Tx Function to be disabled
+ *
+ * @return void
+ */
+void bna_txf_enable(struct bna_dev_s *bna_dev, unsigned int txf_id);
+
+/*
+ *
+ *
+ *   R X   I N D I R E C T I O N   T A B L E   D E F I N E S
+ *
+ *
+ */
+/**
+ *  Receive-Function RIT (Receive Indirection Table)
+ *
+ *  RIT is required by RSS.  However, in Catapult-LL, RIT must still be
+ *  present for non-RSS.  For non-RSS it just defines the unicast RxQs
+ *  associated to a function.
+ *
+ *  Each entry in the RIT holds two RxQs which are either Small and Large
+ *  Buffer RxQs or Header and Data Buffer RxQs.  "large_rxq_id" is used when
+ *  neither Small/Large or Header-Data Split is configured.
+ */
+struct bna_rit_entry {
+	u8  large_rxq_id;   /* used for either large or data buffers */
+	u8  small_rxq_id;   /* used for either small or header buffers */
+};
+
+
+/**
+ * bna_rit_config_set()
+ *
+ *   Loads RIT entries "rit" into RIT starting from RIT index "rit_offset".
+ *   Care must be taken not to overlap regions within the RIT.
+ *
+ * @param[in]  dev  	  - pointer to BNA device structure
+ * @param[in]  rit_offset - receive-indirection-table index.
+ * @param[in]  rit[]	  - receive-indirection-table segment.
+ * @param[in]  rit_size   - size of receive-indirection-table segment.
+ *
+ * @return void
+ */
+void bna_rit_config_set(struct bna_dev_s *dev, unsigned int rit_offset,
+		const struct bna_rit_entry rit[], unsigned int rit_size);
+
+
+/*
+ *******************************************************************************
+ *
+ *   R X   F U N C T I O N   D E F I N E S
+ *
+ *******************************************************************************
+ */
+
+/* RxF RSS (Receive Side Scaling) */
+#define	BNA_RSS_V4_TCP  	(1 << 11)
+#define	BNA_RSS_V4_IP   	(1 << 10)
+#define	BNA_RSS_V6_TCP  	(1 <<  9)
+#define	BNA_RSS_V6_IP   	(1 <<  8)
+typedef u16 bna_rxf_rss_type_t;
+
+#define BNA_RSS_HASH_KEY_LEN 10 /* in words */
+
+struct bna_rxf_rss {
+	bna_rxf_rss_type_t type;
+	u8 	hash_mask;
+	u32 	toeplitz_hash_key[BNA_RSS_HASH_KEY_LEN];
+};
+
+
+/* RxF HDS (Header Data Split) */
+#define	BNA_HDS_V4_TCP  	(1 << 11)
+#define	BNA_HDS_V4_UDP  	(1 << 10)
+#define	BNA_HDS_V6_TCP  	(1 <<  9)
+#define	BNA_HDS_V6_UDP  	(1 <<  8)
+#define	BNA_HDS_FORCED  	(1 <<  7)
+typedef u16 bna_rxf_hds_type_t;
+
+
+#define BNA_HDS_FORCE_OFFSET_MIN	24  /* bytes */
+#define BNA_HDS_FORCE_OFFSET_MAX	60  /* bytes */
+
+
+struct bna_rxf_hds {
+	bna_rxf_hds_type_t	type;		/* OR of bna_rxf_hds_type_t */
+	u8 		header_size;	/* max header size for split */
+	u8 		forced_offset;	/* HDS at a force offset */
+};
+
+
+/* RxF Control Flags */
+#define	BNA_RXF_CF_SM_LG_RXQ			(1 << 15)
+#define	BNA_RXF_CF_DEFAULT_VLAN 		(1 << 14)
+#define	BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE	(1 << 13)
+#define	BNA_RXF_CF_VLAN_STRIP   		(1 << 12)
+#define	BNA_RXF_CF_RSS_ENABLE   		(1 <<  8)
+typedef u16 bna_rxf_ctrl_flag_t;
+
+
+/* RxF Configuration Structure */
+struct bna_rxf_config {
+	u8 	rit_offset; 	/* offset into RIT */
+	u8 	mcast_rxq_id;	/* multicast RxQ ID */
+	u16	default_vlan;	/* default VLAN for untagged frames */
+	bna_rxf_ctrl_flag_t flags;  	/* OR of bna_rxf_ctrl_flag_t */
+	struct bna_rxf_hds  hds;	/* valid when BNA_RXF_SM_LG_RXQ == 0 */
+	struct bna_rxf_rss  rss;	/* valid when BNA_RXF_RSS_ENABLE == 1 */
+};
+
+
+/**
+ * bna_rxf_config_set()
+ *
+ *   For RxF "rxf_id", it configures RxF based on "cfg_ptr", and indicates
+ *   to the statistics collector to collect statistics for this Rx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  cfg_ptr - pointer to rx-function configuration.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_config_set(struct bna_dev_s *dev, unsigned int rxf_id,
+				const struct bna_rxf_config *cfg_ptr);
+
+
+/**
+ * bna_rxf_config_clear()
+ *
+ *   For RxF "rxf_id", it clear its configuration and indicates to the
+ *   statistics collector to stop collecting statistics for this
+ *   Rx-Function.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ *
+ * @return  void
+ */
+void bna_rxf_config_clear(struct bna_dev_s *dev, unsigned int rxf_id);
+
+/**
+ * bna_multi_rxf_active()
+ *
+ *  Disables/Enables the Rx Function without clearing the configuration
+ *  Also disables/enables collection of statistics.
+ *
+ * @param[in] bna_dev   - Pointer to BNA BNA device handle
+ * @param[in] rxf_id	- Id of the Rx Function to be disabled
+ * @param[in] enable	- 1 = enable, 0 = disable
+ *
+ * @return BNA_OK if mbox command succeeded else BNA_FAIL
+ */
+enum bna_status_e bna_multi_rxf_active(struct bna_dev_s *dev, u64 rxf_id_mask,
+    u8 enable);
+/**
+ * bna_rxf_disable()
+ *
+ *  Disables the Rx Function without clearing the configuration
+ *  Also disables collection of statistics.
+ *
+ * @param[in] bna_dev   - Pointer to BNA BNA device handle
+ * @param[in] rxf_id	- Id of the Rx Function to be disabled
+ *
+ * @return BNA_OK if mbox command succeeded else BNA_FAIL
+ */
+enum bna_status_e bna_rxf_disable(struct bna_dev_s *bna_dev,
+	unsigned int rxf_id);
+
+/**
+ * bna_multi_rxf_disable()
+ *
+ *  Disables multiple Rx Functions as per the mask
+ *  Also disables collection of statistics.
+ *
+ * @param[in] dev 		- Pointer to BNA device handle
+ * @param[in] rxf_id_mask    	- Mask of the functions to be
+				  disabled
+ *
+ * @return    BNA_OK if mbox command succeeded, else BNA_FAIL
+ */
+#define bna_multi_rxf_disable(dev, rxf_id_mask)	\
+		bna_multi_rxf_active((dev), (rxf_id_mask), 0)
+
+/**
+ * bna_rxf_enable()
+ *
+ *  Enables the Rx Function
+ *
+ * @param[in] bna_dev   - Pointer to BNA BNA device handle
+ * @param[in] rxf_id	- Id of the Rx Function to be disabled
+ *
+ * @return BNA_OK if mbox command succeeded else BNA_FAIL
+ */
+enum bna_status_e bna_rxf_enable(struct bna_dev_s *bna_dev,
+	unsigned int rxf_id);
+
+/**
+ * bna_multi_rxf_enable()
+ *
+ *  Enables multiple Rx Functions as per the mask
+ *  Also enables collection of statistics.
+ *
+ * @param[in] dev               - Pointer to BNA device handle
+ * @param[in] rxf_id_mask       - Mask of the functions to be
+ *                                enabled
+ *
+ * @return    BNA_OK if mbox command succeeded, else BNA_FAIL
+ */
+#define bna_multi_rxf_enable(dev, rxf_id_mask)	\
+		bna_multi_rxf_active((dev), (rxf_id_mask), 1)
+
+
+/* TODO : Delete when windows migration is complete */
+void bna_rxf_disable_old(struct bna_dev_s *dev, unsigned int rxf_id);
+
+
+/**
+ * bna_rxf_ucast_mac_set()
+ *
+ *   For RxF "rxf_id", it overwrites the burnt-in unicast MAC with
+ *   the one specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_ptr - pointer to unicast MAC address.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_ucast_mac_set(struct bna_dev_s *dev,
+		unsigned int rxf_id, const u8 *mac_ptr);
+
+
+/**
+ * bna_rxf_ucast_mac_add()
+ *
+ *   For RxF "rxf_id", it adds the unicast MAC specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_ptr - pointer to unicast MAC address.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_ucast_mac_add(struct bna_dev_s *dev,
+	unsigned int rxf_id, const u8 *mac_ptr);
+
+
+/**
+ * bna_rxf_ucast_mac_del()
+ *
+ *   For RxF "rxf_id", it deletes the unicast MAC specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_ptr - pointer to unicast MAC address.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_ucast_mac_del(struct bna_dev_s *dev,
+		unsigned int rxf_id, const u8 *mac_ptr);
+
+
+/**
+ * bna_rxf_mcast_mac_add()
+ *
+ *   For RxF "rxf_id", it adds the multicast MAC specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_ptr - pointer to multicast MAC address.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_mcast_mac_add(struct bna_dev_s *dev,
+	unsigned int rxf_id, const u8 *mac_ptr);
+
+
+/**
+ * bna_rxf_mcast_mac_del()
+ *
+ *   For RxF "rxf_id", it deletes the multicast MAC specified by "mac_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_ptr - pointer to multicast MAC address.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_mcast_mac_del(struct bna_dev_s *dev,
+	unsigned int rxf_id, const u8 *mac_ptr);
+
+/**
+ *  bna_rxf_broadcast()
+ *
+ *  For RxF "rxf_id", it enables/disables the broadcast address.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable broadcast address
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_broadcast(struct bna_dev_s *bna_dev,
+		unsigned int rxf_id, enum bna_enable_e enable);
+
+/**
+ * bna_rxf_mcast_mac_set_list()
+ *
+ *  For RxF "rxf_id", it sets the multicast MAC addresses
+ *  specified by "mac_addr_ptr". The function first deletes the
+ *  MAC addresses in the existing list that is not found in the
+ *  new list. It then adds the new addresses that ar ein the new
+ *  list but not in the old list. It then replaces the old list
+ *  with the new list in the bna_dev structure.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  mac_addr_ptr - pointer to the list of mac
+ *  	 adddresses to set
+ * @param[in]  mac_addr_num - number of mac addresses in the
+ *  	 list
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e
+bna_rxf_mcast_mac_set_list(struct bna_dev_s *bna_dev, unsigned int rxf_id,
+		const u8 *mac_addr_ptr , unsigned int mac_addr_num);
+
+/**
+ * bna_mcast_mac_reset_list()
+ *
+ *  Resets the multicast MAC address list kept by driver.
+ *  Called when the hw gets reset.
+ *
+ * @param[in]  dev  - pointer to BNA device structure
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void
+bna_mcast_mac_reset_list(struct bna_dev_s *bna_dev);
+
+/**
+ * bna_rxf_mcast_filter()
+ *
+ *   For RxF "rxf_id", it enables/disables the Multicast Filter.
+ *   Disabling the Multicast Filter allows reception of any multicast frame.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable Multicast Filtering.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_mcast_filter(struct bna_dev_s *dev,
+	unsigned int rxf_id, enum bna_enable_e enable);
+
+/**
+ * bna_rxf_mcast_del_all()
+ *
+ *   For RxF "rxf_id", it clears the MCAST cam and MVT.
+ *   This functionality is required by some of the drivers.
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_mcast_del_all(struct bna_dev_s *dev,
+	unsigned int rxf_id);
+
+
+/**
+ * bna_rxf_vlan_add()
+ *
+ *   For RxF "rxf_id", it adds this function as a member of the
+ *   specified "vlan_id".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  vlan_id - VLAN ID.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void   bna_rxf_vlan_add(struct bna_dev_s *dev, unsigned int rxf_id,
+			       unsigned int vlan_id);
+
+
+/**
+ * bna_rxf_vlan_del()
+ *
+ *   For RxF "rxf_id", it removes this function as a member of the
+ *   specified "vlan_id".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  rxf_id  - rx-function ID.
+ * @param[in]  vlan_id - VLAN ID.
+ *
+ * @return void
+ */
+void bna_rxf_vlan_del(struct bna_dev_s *dev, unsigned int rxf_id,
+			       unsigned int vlan_id);
+
+
+/**
+ * bna_rxf_vlan_filter()
+ *
+ *   For RxF "rxf_id", it enables/disables the VLAN filter.
+ *   Disabling the VLAN Filter allows reception of any VLAN-tagged frame.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable VLAN Filtering.
+ *
+ * @return void
+ */
+void bna_rxf_vlan_filter(struct bna_dev_s *dev, unsigned int rxf_id,
+				  enum bna_enable_e enable);
+
+/**
+ * bna_rxf_vlan_del_all()
+ *
+ *   For RxF "rxf_id", it clears all the VLANs.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+
+ *
+ * @return void
+ */
+void bna_rxf_vlan_del_all(struct bna_dev_s *bna_dev, unsigned int rxf_id);
+
+/**
+ * bna_rxf_promiscuous_mode()
+ *
+ *   For RxF "rxf_id", it enables/disables promiscuous-mode.
+ *   Only one RxF is allowed to be in promiscuous-mode, and will only disable
+ *   the promiscuous-mode if the RxF ID is the one in promiscuous-mode.
+ *   Must be called after the RxF has been configured.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable promiscuous-mode..
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_promiscuous(struct bna_dev_s *dev,
+	unsigned int rxf_id, enum bna_enable_e enable);
+
+
+/* FIXME : Remove BNA_VM_OS */
+#ifdef BNA_VM_OS
+/**
+ * bna_rxf_default_mode()
+ *
+ *   For RxF "rxf_id", it enables/disables default mode.
+ *   Only one RxF is allowed to be in default-mode, and will only disable
+ *   the default-mode if the RxF ID is the one in default-mode.
+ *   Must be called after the RxF has been configured.
+ *   Must remove all unicast MAC associated to this RxF.
+ *
+ * @param[in]  dev    - pointer to BNA device structure
+ * @param[in]  rxf_id - rx-function ID.
+ * @param[in]  enable - enable/disable default mode..
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_default_mode(struct bna_dev_s *dev,
+	unsigned int rxf_id, enum bna_enable_e enable);
+#endif  /* BNA_VM_OS */
+
+/**
+ * bna_rxf_frame_stats_get()
+ *
+ *   For RxF "rxf_id", it loads frame statistics into "stats_ptr".
+ *
+ * @param[in]  dev  	 - pointer to BNA device structure
+ * @param[in]  rxf_id    - rx-function ID.
+ * @param[out] stats_ptr - pointer to rx-function statistics structure
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void bna_rxf_frame_stats_get(struct bna_dev_s *dev, unsigned int rxf_id,
+				      struct bna_stats_rxf **stats_ptr);
+
+/**
+ * bna_txf_frame_stats_get()
+ *
+ *   For TxF "txf_id", it loads frame statistics into "stats_ptr".
+ *
+ * @param[in]  dev     - pointer to BNA device structure
+ * @param[in]  txf_id    - tx-function ID.
+ * @param[out] stats_ptr - pointer to tx-function statistics structure
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void bna_txf_frame_stats_get(struct bna_dev_s *dev, unsigned int txf_id,
+				      struct bna_stats_txf **stats_ptr);
+
+/**
+ *  bna_mac_rx_stats_get()
+ *
+ *  Loads MAC Rx statistics into "stats_ptr".
+ *
+ * @param[in]  dev	 - pointer to BNA device structure
+
+ * @param[out]  stats_ptr - pointer to stats structure
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void bna_mac_rx_stats_get(struct bna_dev_s *bna_dev,
+				   struct cna_stats_mac_rx **stats_ptr);
+
+/**
+ *  bna_mac_tx_stats_get()
+ *
+ *  Loads MAC Tx statistics into "stats_ptr".
+ *
+ * @param[in]  dev	 - pointer to BNA device structure
+
+ * @param[out]  stats_ptr - pointer to stats structure
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void bna_mac_tx_stats_get(struct bna_dev_s *bna_dev,
+				   struct cna_stats_mac_tx **stats_ptr);
+
+/**
+ *  bna_all_stats_get()
+ *
+ *  Loads all statistics into "stats_ptr".
+ *
+ * @param[in]  dev	 - pointer to BNA device structure
+
+ * @param[out]  stats_ptr - pointer to stats structure
+ *
+ * @return void
+ */
+void bna_all_stats_get(struct bna_dev_s *bna_dev,
+				  struct bna_stats **stats_ptr);
+/**
+ * bna_stats_get()
+ *
+ *   Get the statistics from the device. This function needs to
+ *   be scheduled every second to get periodic update of the
+ *   statistics data from hardware.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure.
+ *
+ * @return void
+ */
+enum bna_status_e bna_stats_get(struct bna_dev_s *dev);
+
+/**
+ * bna_stats_clear()
+ *
+ *   Clear the statistics in the device.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_stats_clear(struct bna_dev_s *bna_dev);
+
+/**
+ * bna_rxf_stats_clear()
+ *
+ *   Clear the statistics for specified txf.
+ *
+ * @param[in]   dev        - pointer to BNA device structure.
+ * @param[in]  rxf_id      - rx-function ID.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_rxf_stats_clear(struct bna_dev_s *dev,
+	unsigned int rxf_id);
+
+/**
+ * bna_lldp_stats_clear()
+ *
+ *   Clear the lldp-dcbcx statistics in the device.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_lldp_stats_clear(struct bna_dev_s *bna_dev);
+
+/**
+ * bna_get_cfg_req()
+ *
+ *   Gets the LLDP-DCBCXP Config from the f/w.
+ *
+ * @param[in]   dev 	      - pointer to BNA device structure.
+ * @param[in]   dma_addr_bna  - dma address to return the config.
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_get_cfg_req(struct bna_dev_s *bna_dev,
+	struct bna_dma_addr *dma_addr_bna);
+
+/**
+
+* bna_get_cee_stats_req()
+*
+*   Gets the LLDP-DCBCXP stats from the f/w.
+*
+* @param[in]   dev           - pointer to BNA device structure.
+* @param[in]   dma_addr_bna  - dma address to return the config.
+*
+* @return BNA_OK   - successful
+* @return BNA_FAIL - failed on sanity checks.
+*/
+enum bna_status_e bna_get_cee_stats_req(struct bna_dev_s *bna_dev,
+	struct bna_dma_addr *dma_addr_bna);
+
+/**
+ * bna_stats_process()
+ *
+ *   Process the statistics data DMAed from the device. This
+ *   function needs to be scheduled upon getting an asynchronous
+ *   notification from the firmware.
+ *
+ * @param[in]   dev 	  - pointer to BNA device structure.
+ *
+ * @return void
+ */
+void bna_stats_process(struct bna_dev_s *bna_dev);
+
+/**
+ * bna_init()
+ *
+ *   Called by the driver during initialization. The driver is
+ *   expected to allocate struct bna_dev_s structure for the BNA layer.
+ *   Should be called with the lock held.
+ *
+ * @param[in]  bna_handle  - pointer to BNA device structure
+ * 			     allocated by the calling driver
+ * @param[in]  bar0 	   - BAR0 value
+ * @param[in]  stats	   - pointer to stats host buffer
+ * @param[in]  stats_dma   - pointer to DMA value for stats
+ * @param[in]  trcmod      - pointer to struct bfa_trc_mod_s
+ *			     (for Interrupt Moderation)
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+void bna_init(struct bna_dev_s *bna_handle, void * bar0,
+    void *stats, struct bna_dma_addr stats_dma, struct bfa_trc_mod_s *trcmod);
+
+/**
+ * bna_uninit()
+ *
+ *   Called by the driver during removal/unload.
+ *
+ * @param[in]  bna_handle  - pointer to BNA device structure
+ * 			     allocated by the calling driver
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_uninit(void *bna_handle);
+
+/**
+ * bna_cleanup()
+ *
+ *   Called by the driver from the hb_fail callback to
+ *   to let bna do the cleanup.
+ *   This should be called before driver frees memory.
+ *   Should be called with the lock held.
+ *
+ * @param[in]  bna_handle  - pointer to BNA device structure
+ * 			     allocated by the calling driver
+ *
+ * @return BNA_OK   - successful
+ * @return BNA_FAIL - failed on sanity checks.
+ */
+enum bna_status_e bna_cleanup(void *bna_handle);
+
+#endif  /* __BNA_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_hwreg.h net-next-2.6-mod/drivers/net/bna/bna_hwreg.h
--- net-next-2.6-orig/drivers/net/bna/bna_hwreg.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_hwreg.h	2009-10-31 21:34:48.216534000 -0700
@@ -0,0 +1,1004 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See <license_file> for copyright and licensing details.
+ */
+
+/*
+ *  bna_hwreg.h Catapult host block register definitions
+ *
+ */
+
+#ifndef __BNA_HWREG_H__
+#define __BNA_HWREG_H__
+
+#include <bfi/bfi_ctreg.h>
+
+/**************************************************************
+ *               REGISTER ACCESS
+ **************************************************************/
+/**
+ * CPE Block Register Address Offset from BAR0
+ */
+	/* TODO */
+/**
+ * RME Block Register Address Offset from BAR0
+ */
+	/* TODO */
+/**
+ * SGM Block Register Address Offset from BAR0
+ */
+	/* TODO */
+
+/**
+ * DMA Block Register Host Window Start Address
+ */
+#define DMA_BLK_REG_ADDR		0x00013000
+/**
+ * DMA Block Internal Registers
+ */
+#define DMA_CTRL_REG0			(DMA_BLK_REG_ADDR + 0x000)
+#define DMA_CTRL_REG1			(DMA_BLK_REG_ADDR + 0x004)
+#define DMA_ERR_INT_STATUS		(DMA_BLK_REG_ADDR + 0x008)
+#define DMA_ERR_INT_ENABLE		(DMA_BLK_REG_ADDR + 0x00c)
+#define DMA_ERR_INT_STATUS_SET		(DMA_BLK_REG_ADDR + 0x010)
+
+/**
+ * APP Block Register Address Offset from BAR0
+ */
+#define APP_BLK_REG_ADDR		0x00014000
+
+/**
+ * Host Function Interrupt Mask Registers
+ */
+#define HOSTFN0_INT_MASK		(APP_BLK_REG_ADDR + 0x004)
+#define HOSTFN1_INT_MASK		(APP_BLK_REG_ADDR + 0x104)
+#define HOSTFN2_INT_MASK		(APP_BLK_REG_ADDR + 0x304)
+#define HOSTFN3_INT_MASK		(APP_BLK_REG_ADDR + 0x404)
+
+/**
+ * Host Function PCIe Error Registers
+ * Duplicates "Correctable" & "Uncorrectable"
+ * registers in PCIe Config space.
+ */
+#define FN0_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x014)
+#define FN1_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x114)
+#define FN2_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x314)
+#define FN3_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x414)
+
+/**
+ * Host Function Error Type Status Registers
+ */
+#define FN0_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x018)
+#define FN1_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x118)
+#define FN2_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x318)
+#define FN3_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x418)
+/**
+ * Host Function Error Type Mask Registers
+ */
+#define FN0_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x01c)
+#define FN1_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x11c)
+#define FN2_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x31c)
+#define FN3_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x41c)
+
+/**
+ * Catapult Host Semaphore Status Registers (App block)
+ */
+#define HOST_SEM_STS0_REG		(APP_BLK_REG_ADDR + 0x630)
+#define HOST_SEM_STS1_REG		(APP_BLK_REG_ADDR + 0x634)
+#define HOST_SEM_STS2_REG		(APP_BLK_REG_ADDR + 0x638)
+#define HOST_SEM_STS3_REG		(APP_BLK_REG_ADDR + 0x63c)
+#define HOST_SEM_STS4_REG		(APP_BLK_REG_ADDR + 0x640)
+#define HOST_SEM_STS5_REG		(APP_BLK_REG_ADDR + 0x644)
+#define HOST_SEM_STS6_REG		(APP_BLK_REG_ADDR + 0x648)
+#define HOST_SEM_STS7_REG		(APP_BLK_REG_ADDR + 0x64c)
+
+/**
+ * PCIe Misc Register
+ * Check catapult_spec.pdf for details
+ */
+#define PCIE_MISC_REG			(APP_BLK_REG_ADDR + 0x200)
+/**
+ * Temp Sensor Control Registers
+ */
+#define TEMPSENSE_CNTL_REG		(APP_BLK_REG_ADDR + 0x250)
+#define TEMPSENSE_STAT_REG		(APP_BLK_REG_ADDR + 0x254)
+
+/**
+ * APP Block local error registers
+ */
+#define APP_LOCAL_ERR_STAT		(APP_BLK_REG_ADDR + 0x258)
+#define APP_LOCAL_ERR_MSK		(APP_BLK_REG_ADDR + 0x25c)
+
+/**
+ * PCIe Link Error registers
+ */
+#define PCIE_LNK_ERR_STAT		(APP_BLK_REG_ADDR + 0x260)
+#define PCIE_LNK_ERR_MSK		(APP_BLK_REG_ADDR + 0x264)
+
+/**
+ * FCoE/FIP Ethertype Register
+ * 31:16 -- Chip wide value for FIP type
+ * 15:0  -- Chip wide value for FCoE type
+ */
+#define FCOE_FIP_ETH_TYPE		(APP_BLK_REG_ADDR + 0x280)
+
+/**
+ * Reserved Ethertype Register
+ * 31:16 -- Reserved
+ * 15:0  -- Other ethertype
+ */
+#define RESV_ETH_TYPE			(APP_BLK_REG_ADDR + 0x284)
+
+/**
+ * Host Command Status Registers
+ * Each set consists of 3 registers :
+ * clear, set, cmd
+ * 16 such register sets in all
+ * See catapult_spec.pdf for detailed functionality
+ * Put each type in a single macro accessed by _num ?
+ */
+#define HOST_CMDSTS0_CLR_REG		(APP_BLK_REG_ADDR + 0x500)
+#define HOST_CMDSTS0_SET_REG		(APP_BLK_REG_ADDR + 0x504)
+#define HOST_CMDSTS0_REG		(APP_BLK_REG_ADDR + 0x508)
+#define HOST_CMDSTS1_CLR_REG		(APP_BLK_REG_ADDR + 0x510)
+#define HOST_CMDSTS1_SET_REG		(APP_BLK_REG_ADDR + 0x514)
+#define HOST_CMDSTS1_REG		(APP_BLK_REG_ADDR + 0x518)
+#define HOST_CMDSTS2_CLR_REG		(APP_BLK_REG_ADDR + 0x520)
+#define HOST_CMDSTS2_SET_REG		(APP_BLK_REG_ADDR + 0x524)
+#define HOST_CMDSTS2_REG		(APP_BLK_REG_ADDR + 0x528)
+#define HOST_CMDSTS3_CLR_REG		(APP_BLK_REG_ADDR + 0x530)
+#define HOST_CMDSTS3_SET_REG		(APP_BLK_REG_ADDR + 0x534)
+#define HOST_CMDSTS3_REG		(APP_BLK_REG_ADDR + 0x538)
+#define HOST_CMDSTS4_CLR_REG		(APP_BLK_REG_ADDR + 0x540)
+#define HOST_CMDSTS4_SET_REG		(APP_BLK_REG_ADDR + 0x544)
+#define HOST_CMDSTS4_REG		(APP_BLK_REG_ADDR + 0x548)
+#define HOST_CMDSTS5_CLR_REG		(APP_BLK_REG_ADDR + 0x550)
+#define HOST_CMDSTS5_SET_REG		(APP_BLK_REG_ADDR + 0x554)
+#define HOST_CMDSTS5_REG		(APP_BLK_REG_ADDR + 0x558)
+#define HOST_CMDSTS6_CLR_REG		(APP_BLK_REG_ADDR + 0x560)
+#define HOST_CMDSTS6_SET_REG		(APP_BLK_REG_ADDR + 0x564)
+#define HOST_CMDSTS6_REG		(APP_BLK_REG_ADDR + 0x568)
+#define HOST_CMDSTS7_CLR_REG		(APP_BLK_REG_ADDR + 0x570)
+#define HOST_CMDSTS7_SET_REG		(APP_BLK_REG_ADDR + 0x574)
+#define HOST_CMDSTS7_REG		(APP_BLK_REG_ADDR + 0x578)
+#define HOST_CMDSTS8_CLR_REG		(APP_BLK_REG_ADDR + 0x580)
+#define HOST_CMDSTS8_SET_REG		(APP_BLK_REG_ADDR + 0x584)
+#define HOST_CMDSTS8_REG		(APP_BLK_REG_ADDR + 0x588)
+#define HOST_CMDSTS9_CLR_REG		(APP_BLK_REG_ADDR + 0x590)
+#define HOST_CMDSTS9_SET_REG		(APP_BLK_REG_ADDR + 0x594)
+#define HOST_CMDSTS9_REG		(APP_BLK_REG_ADDR + 0x598)
+#define HOST_CMDSTS10_CLR_REG		(APP_BLK_REG_ADDR + 0x5A0)
+#define HOST_CMDSTS10_SET_REG		(APP_BLK_REG_ADDR + 0x5A4)
+#define HOST_CMDSTS10_REG		(APP_BLK_REG_ADDR + 0x5A8)
+#define HOST_CMDSTS11_CLR_REG		(APP_BLK_REG_ADDR + 0x5B0)
+#define HOST_CMDSTS11_SET_REG		(APP_BLK_REG_ADDR + 0x5B4)
+#define HOST_CMDSTS11_REG		(APP_BLK_REG_ADDR + 0x5B8)
+#define HOST_CMDSTS12_CLR_REG		(APP_BLK_REG_ADDR + 0x5C0)
+#define HOST_CMDSTS12_SET_REG		(APP_BLK_REG_ADDR + 0x5C4)
+#define HOST_CMDSTS12_REG		(APP_BLK_REG_ADDR + 0x5C8)
+#define HOST_CMDSTS13_CLR_REG		(APP_BLK_REG_ADDR + 0x5D0)
+#define HOST_CMDSTS13_SET_REG		(APP_BLK_REG_ADDR + 0x5D4)
+#define HOST_CMDSTS13_REG		(APP_BLK_REG_ADDR + 0x5D8)
+#define HOST_CMDSTS14_CLR_REG		(APP_BLK_REG_ADDR + 0x5E0)
+#define HOST_CMDSTS14_SET_REG		(APP_BLK_REG_ADDR + 0x5E4)
+#define HOST_CMDSTS14_REG		(APP_BLK_REG_ADDR + 0x5E8)
+#define HOST_CMDSTS15_CLR_REG		(APP_BLK_REG_ADDR + 0x5F0)
+#define HOST_CMDSTS15_SET_REG		(APP_BLK_REG_ADDR + 0x5F4)
+#define HOST_CMDSTS15_REG		(APP_BLK_REG_ADDR + 0x5F8)
+
+/**
+ * IOQ Block Register Address Offset from BAR0
+ */
+	/* TODO ? */
+/**
+ * IOH Block Register Address Offset from BAR0
+ */
+	/* Required only in FC mode */
+/**
+ * DIP Block Register Address Offset from BAR0
+ */
+	/* Required only in FC mode */
+/**
+ * SIP Block Register Address Offset from BAR0
+ */
+	/* Required only in FC mode */
+
+/**
+ * LPU0 Block Register Address Offset from BAR0
+ * Range 0x18000 - 0x18033
+ */
+#define LPU0_BLK_REG_ADDR		0x00018000
+
+/**
+ * LPU0 Registers
+ * Should they be directly used from host,
+ * except for diagnostics ?
+ * CTL_REG : Control register
+ * CMD_REG : Triggers exec. of cmd. in
+ *           Mailbox memory
+ */
+#define LPU0_MBOX_CTL_REG		(LPU0_BLK_REG_ADDR + 0x000)
+#define LPU0_MBOX_CMD_REG		(LPU0_BLK_REG_ADDR + 0x004)
+#define LPU0_MBOX_LINK_0REG		(LPU0_BLK_REG_ADDR + 0x008)
+#define LPU1_MBOX_LINK_0REG		(LPU0_BLK_REG_ADDR + 0x00c)
+#define LPU0_MBOX_STATUS_0REG		(LPU0_BLK_REG_ADDR + 0x010)
+#define LPU1_MBOX_STATUS_0REG		(LPU0_BLK_REG_ADDR + 0x014)
+#define LPU0_ERR_STATUS_REG		(LPU0_BLK_REG_ADDR + 0x018)
+#define LPU0_ERR_SET_REG		(LPU0_BLK_REG_ADDR + 0x020)
+
+/**
+ * LPU1 Block Register Address Offset from BAR0
+ * Range 0x18400 - 0x18433
+ */
+#define LPU1_BLK_REG_ADDR		0x00018400
+
+/**
+ * LPU1 Registers
+ * Same as LPU0 registers above
+ */
+#define LPU1_MBOX_CTL_REG		(LPU1_BLK_REG_ADDR + 0x000)
+#define LPU1_MBOX_CMD_REG		(LPU1_BLK_REG_ADDR + 0x004)
+#define LPU0_MBOX_LINK_1REG		(LPU1_BLK_REG_ADDR + 0x008)
+#define LPU1_MBOX_LINK_1REG		(LPU1_BLK_REG_ADDR + 0x00c)
+#define LPU0_MBOX_STATUS_1REG		(LPU1_BLK_REG_ADDR + 0x010)
+#define LPU1_MBOX_STATUS_1REG		(LPU1_BLK_REG_ADDR + 0x014)
+#define LPU1_ERR_STATUS_REG		(LPU1_BLK_REG_ADDR + 0x018)
+#define LPU1_ERR_SET_REG		(LPU1_BLK_REG_ADDR + 0x020)
+
+/**
+ * PSS Block Register Address Offset from BAR0
+ * Range 0x18800 - 0x188DB
+ */
+#define PSS_BLK_REG_ADDR		0x00018800
+
+/**
+ * PSS Registers
+ * For details, see catapult_spec.pdf
+ * ERR_STATUS_REG : Indicates error in PSS module
+ * RAM_ERR_STATUS_REG : Indicates RAM module that detected error
+ */
+#define PSS_ERR_STATUS_REG		(PSS_BLK_REG_ADDR + 0x010)
+#define ERR_STATUS_SET			(PSS_BLK_REG_ADDR + 0x018)
+#define PSS_RAM_ERR_STATUS_REG		(PSS_BLK_REG_ADDR + 0x01C)
+
+/**
+ * PSS Semaphore Lock Registers, total 16
+ * First read when unlocked returns 0,
+ * and is set to 1, atomically.
+ * Subsequent reads returns 1.
+ * To clear set the value to 0.
+ * Range : 0x20 to 0x5c
+ */
+#define PSS_SEM_LOCK_REG(_num) 		\
+	(PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+/**
+ * PSS Semaphore Status Registers,
+ * corresponding to the lock registers above
+ */
+#define PSS_SEM_STATUS_REG(_num) 		\
+	(PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
+
+/**
+ * Catapult CPQ Registers
+ * Defines for Mailbox Registers
+ * Used to send mailbox commands to firmware from
+ * host. The data part is written to the MBox
+ * memory, registers are used to indicate that
+ * a commnad is resident in memory.
+ *
+ * Note : LPU0<->LPU1 mailboxes are not listed here
+ */
+#define CPQ_BLK_REG_ADDR		0x00019000
+
+#define HOSTFN0_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x130)
+#define HOSTFN0_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x134)
+#define LPU0_HOSTFN0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x138)
+#define LPU1_HOSTFN0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x13C)
+
+#define HOSTFN1_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x140)
+#define HOSTFN1_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x144)
+#define LPU0_HOSTFN1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x148)
+#define LPU1_HOSTFN1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x14C)
+
+#define HOSTFN2_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x170)
+#define HOSTFN2_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x174)
+#define LPU0_HOSTFN2_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x178)
+#define LPU1_HOSTFN2_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x17C)
+
+#define HOSTFN3_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x180)
+#define HOSTFN3_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x184)
+#define LPU0_HOSTFN3_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x188)
+#define LPU1_HOSTFN3_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x18C)
+
+/**
+ * Host Function Force Parity Error Registers
+ */
+#define HOSTFN0_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x120)
+#define HOSTFN1_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x124)
+#define HOSTFN2_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x128)
+#define HOSTFN3_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x12C)
+
+/**
+ * LL Port[0|1] Halt Mask Registers
+ */
+#define LL_HALT_MSK_P0			(CPQ_BLK_REG_ADDR + 0x1A0)
+#define LL_HALT_MSK_P1			(CPQ_BLK_REG_ADDR + 0x1B0)
+
+/**
+ * LL Port[0|1] Error Mask Registers
+ */
+#define LL_ERR_MSK_P0			(CPQ_BLK_REG_ADDR + 0x1D0)
+#define LL_ERR_MSK_P1			(CPQ_BLK_REG_ADDR + 0x1D4)
+
+/**
+ * TXQ Block Register Address Offset from BAR0
+ */
+	/* TODO :
+	 * For per-port registers, offsets look
+	 * skewed, need clarification
+	 */
+/**
+ * RDS (Rx Frame Data Store) Block Register Address Offset from BAR0
+ */
+	/* Host does not need to access these */
+/**
+ * TDS (Tx Frame Data Store) Block Register Address Offset from BAR0
+ */
+	/* Host does not need to access these */
+/**
+ * BAL Block Register Address Offset from BAR0
+ */
+	/* TODO : Some of these may be needed */
+
+/**
+ * EMC FLI (Flash Controller) Block Register Address Offset from BAR0
+ */
+#define FLI_BLK_REG_ADDR		0x0001D000
+
+/**
+ * EMC FLI Registers
+ */
+#define FLI_CMD_REG			(FLI_BLK_REG_ADDR + 0x000)
+#define FLI_ADDR_REG			(FLI_BLK_REG_ADDR + 0x004)
+#define FLI_CTL_REG			(FLI_BLK_REG_ADDR + 0x008)
+#define FLI_WRDATA_REG			(FLI_BLK_REG_ADDR + 0x00C)
+#define FLI_RDDATA_REG			(FLI_BLK_REG_ADDR + 0x010)
+#define FLI_DEV_STATUS_REG		(FLI_BLK_REG_ADDR + 0x014)
+#define FLI_SIG_WD_REG			(FLI_BLK_REG_ADDR + 0x018)
+/*
+ * H/W document lists the following vendor ID register as
+ * FLI_ERR_VENDOR_REG -- typo ?
+ * RO register
+ * 31:16 -- Vendor Id
+ * 15:0  -- Device Id
+ */
+#define FLI_DEV_VENDOR_REG		(FLI_BLK_REG_ADDR + 0x01C)
+#define FLI_ERR_STATUS_REG		(FLI_BLK_REG_ADDR + 0x020)
+
+/**
+ * FPG (FC Port Group) Block Register Address Offset from BAR0
+ */
+	/* FC driver specific */
+
+/**
+ * RAD (RxAdm) Block Register Address Offset from BAR0
+ * RAD0 Range : 0x20000 - 0x203FF
+ * RAD1 Range : 0x20400 - 0x207FF
+ */
+#define RAD0_BLK_REG_ADDR		0x00020000
+#define RAD1_BLK_REG_ADDR		0x00020400
+
+/**
+ * RAD0 Registers
+ */
+#define RAD0_CTL_REG			(RAD0_BLK_REG_ADDR + 0x000)
+#define RAD0_PE_PARM_REG		(RAD0_BLK_REG_ADDR + 0x004)
+#define RAD0_BCN_REG			(RAD0_BLK_REG_ADDR + 0x008)
+/*
+ * Default function ID register
+ */
+#define RAD0_DEFAULT_REG		(RAD0_BLK_REG_ADDR + 0x00C)
+/*
+ * Default promiscuous ID register
+ */
+#define RAD0_PROMISC_REG		(RAD0_BLK_REG_ADDR + 0x010)
+
+#define RAD0_BCNQ_REG			(RAD0_BLK_REG_ADDR + 0x014)
+/*
+ * This register selects 1 of 8 PM Q's using
+ * VLAN pri, for non-BCN packets without a VLAN tag
+ */
+#define RAD0_DEFAULTQ_REG		(RAD0_BLK_REG_ADDR + 0x018)
+
+#define RAD0_ERR_STS			(RAD0_BLK_REG_ADDR + 0x01C)
+#define RAD0_SET_ERR_STS		(RAD0_BLK_REG_ADDR + 0x020)
+#define RAD0_ERR_INT_EN			(RAD0_BLK_REG_ADDR + 0x024)
+#define RAD0_FIRST_ERR          (RAD0_BLK_REG_ADDR + 0x028)
+#define RAD0_FORCE_ERR          (RAD0_BLK_REG_ADDR + 0x02C)
+
+#define RAD0_IF_RCVD            (RAD0_BLK_REG_ADDR + 0x030)
+#define RAD0_IF_RCVD_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x034)
+#define RAD0_IF_RCVD_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x038)
+#define RAD0_IF_RCVD_VLAN       (RAD0_BLK_REG_ADDR + 0x03C)
+#define RAD0_IF_RCVD_UCAST       (RAD0_BLK_REG_ADDR + 0x040)
+#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x044)
+#define RAD0_IF_RCVD_UCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x048)
+#define RAD0_IF_RCVD_UCAST_VLAN (RAD0_BLK_REG_ADDR + 0x04C)
+#define RAD0_IF_RCVD_MCAST      (RAD0_BLK_REG_ADDR + 0x050)
+#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x054)
+#define RAD0_IF_RCVD_MCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x058)
+#define RAD0_IF_RCVD_MCAST_VLAN (RAD0_BLK_REG_ADDR + 0x05C)
+#define RAD0_IF_RCVD_BCAST      (RAD0_BLK_REG_ADDR + 0x060)
+#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x064)
+#define RAD0_IF_RCVD_BCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x068)
+#define RAD0_IF_RCVD_BCAST_VLAN (RAD0_BLK_REG_ADDR + 0x06C)
+#define RAD0_DROPPED_FRAMES     (RAD0_BLK_REG_ADDR + 0x070)
+
+#define RAD0_MAC_MAN_1H         (RAD0_BLK_REG_ADDR + 0x080)
+#define RAD0_MAC_MAN_1L         (RAD0_BLK_REG_ADDR + 0x084)
+#define RAD0_MAC_MAN_2H         (RAD0_BLK_REG_ADDR + 0x088)
+#define RAD0_MAC_MAN_2L         (RAD0_BLK_REG_ADDR + 0x08C)
+#define RAD0_MAC_MAN_3H         (RAD0_BLK_REG_ADDR + 0x090)
+#define RAD0_MAC_MAN_3L         (RAD0_BLK_REG_ADDR + 0x094)
+#define RAD0_MAC_MAN_4H         (RAD0_BLK_REG_ADDR + 0x098)
+#define RAD0_MAC_MAN_4L         (RAD0_BLK_REG_ADDR + 0x09C)
+
+
+#define RAD0_LAST4_IP           (RAD0_BLK_REG_ADDR + 0x100)
+
+/**
+ * RAD1 Registers
+ */
+#define RAD1_CTL_REG			(RAD1_BLK_REG_ADDR + 0x000)
+#define RAD1_PE_PARM_REG		(RAD1_BLK_REG_ADDR + 0x004)
+#define RAD1_BCN_REG			(RAD1_BLK_REG_ADDR + 0x008)
+/*
+ * Default function ID register
+ */
+#define RAD1_DEFAULT_REG		(RAD1_BLK_REG_ADDR + 0x00C)
+/*
+ * Promiscuous function ID register
+ */
+#define RAD1_PROMISC_REG		(RAD1_BLK_REG_ADDR + 0x010)
+
+#define RAD1_BCNQ_REG			(RAD1_BLK_REG_ADDR + 0x014)
+/*
+ * This register selects 1 of 8 PM Q's using
+ * VLAN pri, for non-BCN packets without a VLAN tag
+ */
+#define RAD1_DEFAULTQ_REG		(RAD1_BLK_REG_ADDR + 0x018)
+
+#define RAD1_ERR_STS			(RAD1_BLK_REG_ADDR + 0x01C)
+#define RAD1_SET_ERR_STS		(RAD1_BLK_REG_ADDR + 0x020)
+#define RAD1_ERR_INT_EN			(RAD1_BLK_REG_ADDR + 0x024)
+/*
+ * RxAdm Statistics Registers:
+ * F/W will access these, not required immediately for host
+ */
+
+/**
+ * RLB (Rx Loop Back) Block Register Address Offset from BAR0
+ */
+	/* TODO : ?? */
+/**
+ * TXA Block Register Address Offset from BAR0
+ * TXA0 Range : 0x21000 - 0x213FF
+ * TXA1 Range : 0x21400 - 0x217FF
+ */
+#define TXA0_BLK_REG_ADDR		0x00021000
+#define TXA1_BLK_REG_ADDR		0x00021400
+
+/**
+ * TXA Registers
+ */
+#define TXA0_CTRL_REG			(TXA0_BLK_REG_ADDR + 0x000)
+#define TXA1_CTRL_REG			(TXA1_BLK_REG_ADDR + 0x000)
+
+/**
+ * TSO Sequence # Registers (RO)
+ * Total 8 (for 8 queues)
+ * Holds the last seq.# for TSO frames
+ * See catapult_spec.pdf for more details
+ */
+#define TXA0_TSO_TCP_SEQ_REG(_num)		\
+	(TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+#define TXA1_TSO_TCP_SEQ_REG(_num)		\
+	(TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+/**
+ * TSO IP ID # Registers (RO)
+ * Total 8 (for 8 queues)
+ * Holds the last IP ID for TSO frames
+ * See catapult_spec.pdf for more details
+ */
+#define TXA0_TSO_IP_INFO_REG(_num)		\
+	(TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+#define TXA1_TSO_IP_INFO_REG(_num)		\
+	(TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+/**
+ * RXA Block Register Address Offset from BAR0
+ * RXA0 Range : 0x21800 - 0x21BFF
+ * RXA1 Range : 0x21C00 - 0x21FFF
+ */
+#define RXA0_BLK_REG_ADDR		0x00021800
+#define RXA1_BLK_REG_ADDR		0x00021C00
+
+/**
+ * RXA Registers
+ */
+#define RXA0_CTL_REG			(RXA0_BLK_REG_ADDR + 0x040)
+#define RXA1_CTL_REG			(RXA1_BLK_REG_ADDR + 0x040)
+
+/**
+ * PPLB Block Register Address Offset from BAR0
+ * PPLB0 Range : 0x22000 - 0x223FF
+ * PPLB1 Range : 0x22400 - 0x227FF
+ */
+#define PLB0_BLK_REG_ADDR		0x00022000
+#define PLB1_BLK_REG_ADDR		0x00022400
+
+/**
+ * PLB Registers
+ */
+/**
+ * Holds RL timer used time stamps in RLT tagged frames
+ */
+#define PLB0_ECM_TIMER_REG		(PLB0_BLK_REG_ADDR + 0x05C)
+#define PLB1_ECM_TIMER_REG		(PLB1_BLK_REG_ADDR + 0x05C)
+/**
+ * Controls the rate-limiter on each of the priority class
+ */
+#define PLB0_RL_CTL			(PLB0_BLK_REG_ADDR + 0x060)
+#define PLB1_RL_CTL			(PLB1_BLK_REG_ADDR + 0x060)
+/**
+ * Max byte register, total 8, 0-7
+ * see catapult_spec.pdf for details
+ */
+#define PLB0_RL_MAX_BC(_num)			\
+	(PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2))
+#define PLB1_RL_MAX_BC(_num)			\
+	(PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2))
+/**
+ * RL Time Unit Register for priority 0-7
+ * 4 bits per priority
+ * (2^rl_unit)*1us is the actual time period
+ */
+#define PLB0_RL_TU_PRIO			(PLB0_BLK_REG_ADDR + 0x084)
+#define PLB1_RL_TU_PRIO			(PLB1_BLK_REG_ADDR + 0x084)
+/**
+ * RL byte count register,
+ * bytes transmitted in (rl_unit*1)us time period
+ * 1 per priority, 8 in all, 0-7.
+ */
+#define PLB0_RL_BYTE_CNT(_num)			\
+	(PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2))
+#define PLB1_RL_BYTE_CNT(_num)			\
+	(PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2))
+/**
+ * RL Min factor register
+ * 2 bits per priority,
+ * 4 factors possible: 1, 0.5, 0.25, 0
+ * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
+ */
+#define PLB0_RL_MIN_REG			(PLB0_BLK_REG_ADDR + 0x0A8)
+#define PLB1_RL_MIN_REG			(PLB1_BLK_REG_ADDR + 0x0A8)
+/**
+ * RL Max factor register
+ * 2 bits per priority,
+ * 4 factors possible: 1, 0.5, 0.25, 0
+ * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
+ */
+#define PLB0_RL_MAX_REG			(PLB0_BLK_REG_ADDR + 0x0AC)
+#define PLB1_RL_MAX_REG			(PLB1_BLK_REG_ADDR + 0x0AC)
+
+/**
+ * MAC SERDES Address Paging register
+ */
+#define PLB0_EMS_ADD_REG		(PLB0_BLK_REG_ADDR + 0xD0)
+#define PLB1_EMS_ADD_REG		(PLB1_BLK_REG_ADDR + 0xD0)
+
+/**
+ * LL EMS Registers
+ */
+#define LL_EMS0_BLK_REG_ADDR		0x00026800
+#define LL_EMS1_BLK_REG_ADDR		0x00026C00
+
+/**
+ * BPC Block Register Address Offset from BAR0
+ * BPC0 Range : 0x23000 - 0x233FF
+ * BPC1 Range : 0x23400 - 0x237FF
+ */
+#define BPC0_BLK_REG_ADDR		0x00023000
+#define BPC1_BLK_REG_ADDR		0x00023400
+
+/**
+ * BPC Registers
+ */
+	/* TODO */
+/**
+ * PMM Block Register Address Offset from BAR0
+ * PMM0 Range : 0x23800 - 0x23BFF
+ * PMM1 Range : 0x23C00 - 0x23FFF
+ */
+#define PMM0_BLK_REG_ADDR		0x00023800
+#define PMM1_BLK_REG_ADDR		0x00023C00
+/**
+ * PMM Registers
+ */
+	/* TODO */
+
+/**
+ * HQM Block Register Address Offset from BAR0
+ * HQM0 Range : 0x24000 - 0x243FF
+ * HQM1 Range : 0x24400 - 0x247FF
+ */
+#define HQM0_BLK_REG_ADDR		0x00024000
+#define HQM1_BLK_REG_ADDR		0x00024400
+/**
+ * HQM Control Register
+ * Controls some aspects of IB
+ * See catapult_spec.pdf for details
+ */
+#define HQM0_CTL_REG			(HQM0_BLK_REG_ADDR + 0x000)
+#define HQM1_CTL_REG			(HQM1_BLK_REG_ADDR + 0x000)
+/**
+ * HQM Stop Q Semaphore Registers.
+ * Only one Queue resource can be stopped at
+ * any given time. This register controls access
+ * to the single stop Q resource.
+ * See catapult_spec.pdf for details
+ */
+#define HQM0_RXQ_STOP_SEM		(HQM0_BLK_REG_ADDR + 0x028)
+#define HQM0_TXQ_STOP_SEM		(HQM0_BLK_REG_ADDR + 0x02C)
+#define HQM1_RXQ_STOP_SEM		(HQM1_BLK_REG_ADDR + 0x028)
+#define HQM1_TXQ_STOP_SEM		(HQM1_BLK_REG_ADDR + 0x02C)
+
+/**
+ * LUT Block Register Address Offset from BAR0
+ * LUT0 Range : 0x25800 - 0x25BFF
+ * LUT1 Range : 0x25C00 - 0x25FFF
+ */
+#define LUT0_BLK_REG_ADDR		0x00025800
+#define LUT1_BLK_REG_ADDR		0x00025C00
+/**
+ * LUT Registers
+ * See catapult_spec.pdf for details
+ */
+#define LUT0_ERR_STS			(LUT0_BLK_REG_ADDR + 0x000)
+#define LUT1_ERR_STS			(LUT1_BLK_REG_ADDR + 0x000)
+#define LUT0_SET_ERR_STS		(LUT0_BLK_REG_ADDR + 0x004)
+#define LUT1_SET_ERR_STS		(LUT1_BLK_REG_ADDR + 0x004)
+
+/**
+ * LDM (Link Layer DMA) Registers
+ */
+	/* TODO */
+
+/**
+ * SGD (Scatter/Gather Database) Registers
+ */
+	/* TODO */
+
+/**
+ * TRC (Debug/Trace) Register Offset from BAR0
+ * Range : 0x26000 -- 0x263FFF
+ */
+#define TRC_BLK_REG_ADDR		0x00026000
+/**
+ * TRC Registers
+ * See catapult_spec.pdf for details of each
+ */
+#define TRC_CTL_REG			(TRC_BLK_REG_ADDR + 0x000)
+#define TRC_MODS_REG			(TRC_BLK_REG_ADDR + 0x004)
+#define TRC_TRGC_REG			(TRC_BLK_REG_ADDR + 0x008)
+#define TRC_CNT1_REG			(TRC_BLK_REG_ADDR + 0x010)
+#define TRC_CNT2_REG			(TRC_BLK_REG_ADDR + 0x014)
+#define TRC_NXTS_REG			(TRC_BLK_REG_ADDR + 0x018)
+#define TRC_DIRR_REG			(TRC_BLK_REG_ADDR + 0x01C)
+/**
+ * TRC Trigger match filters, total 10
+ * Determines the trigger condition
+ */
+#define TRC_TRGM_REG(_num)		\
+	(TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+/**
+ * TRC Next State filters, total 10
+ * Determines the next state conditions
+ */
+#define TRC_NXTM_REG(_num)		\
+	(TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2))
+/**
+ * TRC Store Match filters, total 10
+ * Determines the store conditions
+ */
+#define TRC_STRM_REG(_num)		\
+	(TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2))
+
+
+
+/**************************************************************
+ *               DOORBELLS ACCESS
+ **************************************************************/
+/**
+ * Catapult doorbells
+ * Each doorbell-queue set has
+ * 1 RxQ, 1 TxQ, 2 IBs in that order
+ * Size of each entry in 32 bytes, even though only 1 word
+ * is used. For Non-VM case each doorbell-q set is
+ * separated by 128 bytes, for VM case it is separated
+ * by 4K bytes
+ * Non VM case Range : 0x38000 - 0x39FFF
+ * VM case Range     : 0x100000 - 0x11FFFF
+ * The range applies to both HQMs
+ */
+#define HQM_DOORBELL_BLK_BASE_ADDR	0x00038000
+#define HQM_DOORBELL_VM_BLK_BASE_ADDR	0x00100000
+
+/**************************************************************
+ *               MEMORY ACCESS
+ **************************************************************/
+/**
+ * Catapult H/W Block Memory Access Address
+ * To the host a memory space of 32K (page) is visible
+ * at a time. The address range is from 0x08000 to 0x0FFFF
+ */
+#define HW_BLK_HOST_MEM_ADDR		0x08000
+
+/**
+ * Catapult LUT Memory Access Page Numbers
+ * Range : LUT0 0xa0-0xa1
+ *         LUT1 0xa2-0xa3
+ */
+#define LUT0_MEM_BLK_BASE_PG_NUM	0x000000A0
+#define LUT1_MEM_BLK_BASE_PG_NUM	0x000000A2
+
+/**
+ * Catapult RxFn Database Memory Block Base Offset
+ *
+ * The Rx function database exists in LUT block.
+ * In PCIe space this is accessible as a 256x32
+ * bit block. Each entry in this database is 4
+ * (4 byte) words. Max. entries is 64.
+ * Address of an entry corresponding to a function
+ * = base_addr + (function_no. * 16)
+ */
+#define RX_FNDB_RAM_BASE_OFFSET		0x0000B400
+
+/**
+ * Catapult TxFn Database Memory Block Base Offset Address
+ *
+ * The Tx function database exists in LUT block.
+ * In PCIe space this is accessible as a 64x32
+ * bit block. Each entry in this database is 1
+ * (4 byte) word. Max. entries is 64.
+ * Address of an entry corresponding to a function
+ * = base_addr + (function_no. * 4)
+ */
+#define TX_FNDB_RAM_BASE_OFFSET		0x0000B800
+
+/**
+ * Catapult Unicast CAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x48 bits; mapped to PCIe space
+ * 512x32 bit blocks. For each address, bits
+ * are written in the order : [47:32] and then
+ * [31:0].
+ */
+#define UCAST_CAM_BASE_OFFSET		0x0000A800
+
+/**
+ * Catapult Unicast RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x9 bits.
+ */
+#define UCAST_RAM_BASE_OFFSET		0x0000B000
+
+/**
+ * Catapult Mulicast CAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x48 bits; mapped to PCIe space
+ * 512x32 bit blocks. For each address, bits
+ * are written in the order : [47:32] and then
+ * [31:0].
+ */
+#define MCAST_CAM_BASE_OFFSET		0x0000A000
+
+/**
+ * Catapult VLAN RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 4096x66 bits; mapped to PCIe space as
+ * 8192x32 bit blocks.
+ * All the 4K entries are within the address range
+ * 0x0000 to 0x8000, so in the first LUT page.
+ */
+#define VLAN_RAM_BASE_OFFSET		0x00000000
+
+/**
+ * Catapult Tx Stats RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 1024x33 bits;
+ * Each Tx function has 64 bytes of space
+ */
+#define TX_STATS_RAM_BASE_OFFSET	0x00009000
+
+/**
+ * Catapult Rx Stats RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 1024x33 bits;
+ * Each Rx function has 64 bytes of space
+ */
+#define RX_STATS_RAM_BASE_OFFSET	0x00008000
+/**
+ * Catapult RXA Memory Access Page Numbers
+ */
+#define RXA0_MEM_BLK_BASE_PG_NUM	0x0000008C
+#define RXA1_MEM_BLK_BASE_PG_NUM	0x0000008D
+
+/**
+ * Catapult Multicast Vector Table Base Offset Address
+ *
+ * Exists in RxA memory space.
+ * Organized as 512x65 bit block.
+ * However for each entry 16 bytes allocated (power of 2)
+ * Total size 512*16 bytes.
+ * There are two logical divisions, 256 entries each :
+ * a) Entries 0x00 to 0xff (256) -- Approx. MVT
+ *    Offset 0x000 to 0xFFF
+ * b) Entries 0x100 to 0x1ff (256) -- Exact MVT
+ *    Offsets 0x1000 to 0x1FFF
+ */
+#define MCAST_APPROX_MVT_BASE_OFFSET	0x00000000
+#define MCAST_EXACT_MVT_BASE_OFFSET	0x00001000
+/**
+ * Catapult RxQ Translate Table (RIT) Base Offset Address
+ *
+ * Exists in RxA memory space
+ * Total no. of entries 64
+ * Each entry is 1 (4 byte) word.
+ * 31:12 -- Reserved
+ * 11:0  -- Two 6 bit RxQ Ids
+ */
+#define FUNCTION_TO_RXQ_TRANSLATE	0x00002000
+
+/**
+ * Catapult RxAdm (RAD) Memory Access Page Numbers
+ */
+#define RAD0_MEM_BLK_BASE_PG_NUM	0x00000086
+#define RAD1_MEM_BLK_BASE_PG_NUM	0x00000087
+
+/**
+ * Catapult RSS Table Base Offset Address
+ *
+ * Exists in RAD memory space.
+ * Each entry is 352 bits, but alligned on
+ * 64 byte (512 bit) boundary. Accessed
+ * 4 byte words, the whole entry can be
+ * broken into 11 word accesses.
+ */
+#define RSS_TABLE_BASE_OFFSET		0x00000800
+
+/**
+ * Catapult CPQ Block Page Number
+ * This value is written to the page number registers
+ * to access the memory associated with the mailboxes.
+ */
+#define CPQ_BLK_PG_NUM			0x00000005
+
+/**
+ * Clarification :
+ * LL functions are 2 & 3; can HostFn0/HostFn1
+ * <-> LPU0/LPU1 memories be used ?
+ */
+/**
+ * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory
+ * Per catapult_spec.pdf, the offset of the mbox
+ * memory is in the register space at an offset of 0x200
+ */
+#define CPQ_BLK_REG_MBOX_ADDR		(CPQ_BLK_REG_ADDR + 0x200)
+
+#define HOSTFN_LPU_MBOX			(CPQ_BLK_REG_MBOX_ADDR + 0x000)
+/**
+ * Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory
+ */
+#define LPU_HOSTFN_MBOX			(CPQ_BLK_REG_MBOX_ADDR + 0x080)
+
+/**
+ * Catapult HQM Block Page Number
+ * This is written to the page number register for
+ * the appropriate function to access the memory
+ * associated with HQM
+ */
+#define HQM0_BLK_PG_NUM			0x00000096
+#define HQM1_BLK_PG_NUM			0x00000097
+
+/**
+ * Note that TxQ and RxQ entries are interlaced
+ * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc.
+ */
+
+#define HQM_RXTX_Q_RAM_BASE_OFFSET	0x00004000
+
+/**
+ * CQ Memory
+ * Exists in HQM Memory space
+ * Each entry is 16 (4 byte) words of which
+ * only 12 words are used for configuration
+ * Total 64 entries per HQM memory space
+ */
+#define HQM_CQ_RAM_BASE_OFFSET		0x00006000
+
+/**
+ * Interrupt Block (IB) Memory
+ * Exists in HQM Memory space
+ * Each entry is 8 (4 byte) words of which
+ * only 5 words are used for configuration
+ * Total 128 entries per HQM memory space
+ */
+#define HQM_IB_RAM_BASE_OFFSET		0x00001000
+
+/**
+ * Index Table (IT) Memory
+ * Exists in HQM Memory space
+ * Each entry is 1 (4 byte) word which
+ * is used for configuration
+ * Total 128 entries per HQM memory space
+ */
+#define HQM_INDX_TBL_RAM_BASE_OFFSET	0x00002000
+
+/**
+ * PSS Block Memory Page Number
+ * This is written to the appropriate page number
+ * register to access the CPU memory.
+ * Also known as the PSS secondary memory (SMEM).
+ * Range : 0x180 to 0x1CF
+ * See catapult_spec.pdf for details
+ */
+#define PSS_BLK_PG_NUM			0x00000180
+
+/**
+ * Offsets of different instances of PSS SMEM
+ * 2.5M of continuous 1T memory space : 2 blocks
+ * of 1M each (32 pages each, page=32KB) and 4 smaller
+ * blocks of 128K each (4 pages each, page=32KB)
+ * PSS_LMEM_INST0 is used for firmware download
+ */
+#define PSS_LMEM_INST0			0x00000000
+#define PSS_LMEM_INST1			0x00100000
+#define PSS_LMEM_INST2			0x00200000
+#define PSS_LMEM_INST3			0x00220000
+#define PSS_LMEM_INST4			0x00240000
+#define PSS_LMEM_INST5			0x00260000
+
+#endif /* __BNA_HWREG_H__ */
diff -ruP net-next-2.6-orig/drivers/net/bna/bna_intr.h net-next-2.6-mod/drivers/net/bna/bna_intr.h
--- net-next-2.6-orig/drivers/net/bna/bna_intr.h	1969-12-31 16:00:00.000000000 -0800
+++ net-next-2.6-mod/drivers/net/bna/bna_intr.h	2009-10-31 21:34:48.223540000 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * See LICENSE.bna for copyright and licensing details.
+ *
+ * File for interrupt macros and functions
+ */
+
+#ifndef __BNA_INTR_H__
+#define __BNA_INTR_H__
+
+static inline void
+bna_intx_disable(struct bna_dev_s *dev, u32 *cur_mask)
+{
+		/* Store the original mask */
+		*cur_mask = bna_reg_read(dev->regs.fn_int_mask);
+		bna_reg_write(dev->regs.fn_int_mask, 0xffffffff);
+}
+
+#define bna_intx_enable(dev, new_mask) 			\
+	bna_reg_write((dev)->regs.fn_int_mask, (new_mask))
+
+#define bna_mbox_intr_disable(dev)		\
+	bna_reg_write((dev)->regs.fn_int_mask, 	\
+	     (bna_reg_read((dev)->regs.fn_int_mask) | \
+	     (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)))
+
+#define bna_mbox_intr_enable(dev)		\
+	bna_reg_write((dev)->regs.fn_int_mask, 	\
+	     (bna_reg_read((dev)->regs.fn_int_mask) & \
+	     ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)))
+
+static inline void
+bna_intr_status_get(struct bna_dev_s *dev, u32 *status)
+{
+		*status = bna_reg_read(dev->regs.fn_int_status);
+		/*
+		 * Clear the status bits before returning
+		 * But do not touch the mailbox bits as yet
+		 */
+		/* Write a '1' to clear the required bits */
+		if (*status) {
+				bna_reg_write(dev->regs.fn_int_status,
+					*status &
+					~(__LPU02HOST_MBOX0_STATUS_BITS |
+					__LPU02HOST_MBOX1_STATUS_BITS |
+					__LPU12HOST_MBOX0_STATUS_BITS |
+					__LPU12HOST_MBOX1_STATUS_BITS));
+		}
+}
+
+#define bna_intr_status_get_no_clr(dev, status)		\
+	{*(status) = bna_reg_read((dev)->regs.fn_int_status)}
+
+#define bna_intr_mask_get(dev, mask)		\
+	(*mask) = bna_reg_read((dev)->regs.fn_int_mask)
+
+#define bna_intr_ack(dev, intr_bmap)		\
+	bna_reg_write((dev)->regs.fn_int_status, (intr_bmap))
+
+#define bna_ib_intx_disable(dev, ib_id)		\
+	bna_reg_write((dev)->regs.fn_int_mask, 	\
+	    bna_reg_read((dev)->regs.fn_int_mask) | \
+	    (1 << (ib_id)))
+
+#define bna_ib_intx_enable(dev, ib_id)		\
+	bna_reg_write((dev)->regs.fn_int_mask, 	\
+	    bna_reg_read((dev)->regs.fn_int_mask) & \
+	    ~(1 << (ib_id)))
+
+extern const struct bna_chip_regs_offset reg_offset[];
+#define bna_mbox_msix_idx_set(dev, msix_vector)		\
+	bna_reg_write((dev)->bar0 + reg_offset[(dev)->pci_fn].msix_idx, \
+	    ((msix_vector) & 0x000001ff))
+
+
+#endif /* __BNA_INTR_H__ */
+

^ permalink raw reply

* Re: Subject: [PATCH 1/6] bna: Brocade 10Gb Ethernet device driver
From: Joe Perches @ 2009-11-01  5:23 UTC (permalink / raw)
  To: Rasesh Mody; +Cc: netdev, adapter_linux_open_src_team, Greg Kroah-Hartman
In-Reply-To: <200911010503.nA153Elp019063@blc-10-10.brocade.com>

There are an awful lot of non linux standard
uses in this code set.

Perhaps staging would be a good place to start?


^ permalink raw reply

* Re: Subject: [PATCH 1/6] bna: Brocade 10Gb Ethernet device driver
From: Eric Dumazet @ 2009-11-01  8:02 UTC (permalink / raw)
  To: Rasesh Mody; +Cc: netdev, adapter_linux_open_src_team
In-Reply-To: <200911010503.nA153Elp019063@blc-10-10.brocade.com>

Rasesh Mody a écrit :
> From: Rasesh Mody <rmody@brocade.com>
> 
> This is patch 1/6 which contains linux driver source for
> Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter.
> Re-based source against net-next-2.6 and re-submitting the
> patch with few fixes.
> 
> We wish this patch to be considered for inclusion in net-next-2.6

bnad->netdev->last_rx = jiffies

and

netdev->trans_start = jiffies;

are not necessary, core network handles last_rx/trans_start itself 
and more efficently nowadays.

void bnad_reset_stats(struct net_device *netdev) seems defined but not used.



^ permalink raw reply

* Re: [PATCH net-next-2.6] Driver for the Microchip MCP251x SPI CAN controllers
From: Wolfgang Grandegger @ 2009-11-01  9:31 UTC (permalink / raw)
  To: Christian Pellegrin
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1256824214-21420-1-git-send-email-chripell-VaTbYqLCNhc@public.gmane.org>

Hi Christian,

we already discusses various driver issues on the Socket-CAN ML. Still,
there are a few. In general, please check the usage of {} for if
statements and check if "if (ret)" should be used instead of "if (ret <
0)" if 0 means success and !0 failure. I don't have a MCP251x hardware
at hand, but maybe Paul (on CC now) has a chance to test it. More
comments inline...

Christian Pellegrin wrote:
> Signed-off-by: Christian Pellegrin <chripell-VaTbYqLCNhc@public.gmane.org>

Please use the subject prefix "can: Driver for the..."

> ---
>  drivers/net/can/Kconfig              |    6 +
>  drivers/net/can/Makefile             |    1 +
>  drivers/net/can/mcp251x.c            | 1182 ++++++++++++++++++++++++++++++++++
>  include/linux/can/platform/mcp251x.h |   34 +
>  4 files changed, 1223 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/can/mcp251x.c
>  create mode 100644 include/linux/can/platform/mcp251x.h
> 
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 26d77cc..e987526 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -102,6 +102,12 @@ config CAN_TI_HECC
>  	  Driver for TI HECC (High End CAN Controller) module found on many
>  	  TI devices. The device specifications are available from www.ti.com
>  
> +config CAN_MCP251X
> +	tristate "Microchip MCP251x SPI CAN controllers"
> +	depends on CAN && CAN_DEV && SPI

You can drop the redundant dependency on "CAN".

> +	---help---
> +	  Driver for the Microchip MCP251x SPI CAN controllers.
> +
>  config CAN_DEBUG_DEVICES
>  	bool "CAN devices debugging messages"
>  	depends on CAN
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 31f4ab5..1489181 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -12,5 +12,6 @@ obj-y				+= usb/
>  obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
>  obj-$(CONFIG_CAN_AT91)		+= at91_can.o
>  obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
> +obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
>  
>  ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
> new file mode 100644
> index 0000000..f444cac
> --- /dev/null
> +++ b/drivers/net/can/mcp251x.c
> @@ -0,0 +1,1182 @@
> +/*
> + * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
> + *
> + * MCP2510 support and bug fixes by Christian Pellegrin
> + * <chripell-LERDrqjqfvZg9hUCZPvPmw@public.gmane.org>

Please add your "Copyright ...".

> + *
> + * Copyright 2007 Raymarine UK, Ltd. All Rights Reserved.
> + * Written under contract by:
> + *   Chris Elston, Katalix Systems, Ltd.
> + *
> + * Based on Microchip MCP251x CAN controller driver written by
> + * David Vrabel, Copyright 2006 Arcom Control Systems Ltd.
> + *
> + * Based on CAN bus driver for the CCAN controller written by
> + * - Sascha Hauer, Marc Kleine-Budde, Pengutronix
> + * - Simon Kallweit, intefo AG
> + * Copyright 2007
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * 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. 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + *
> + *
> + * Your platform definition file should specify something like:
> + *
> + * static struct mcp251x_platform_data mcp251x_info = {
> + *         .oscillator_frequency = 8000000,
> + *         .board_specific_setup = &mcp251x_setup,
> + *         .model = CAN_MCP251X_MCP2510,
> + *         .power_enable = mcp251x_power_enable,
> + *         .transceiver_enable = NULL,
> + * };
> + *
> + * static struct spi_board_info spi_board_info[] = {
> + *         {
> + *                 .modalias      = "mcp251x",
> + *                 .platform_data = &mcp251x_info,
> + *                 .irq           = IRQ_EINT13,
> + *                 .max_speed_hz  = 2*1000*1000,
> + *                 .chip_select   = 2,
> + *         },
> + * };
> + *
> + * Please see mcp251x.h for a description of the fields in
> + * struct mcp251x_platform_data.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/netdevice.h>
> +#include <linux/can.h>
> +#include <linux/spi/spi.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/core.h>

I don't think you need "can/core.h"?

> +#include <linux/if_arp.h>

And that one either.

> +#include <linux/dma-mapping.h>
> +#include <linux/delay.h>
> +#include <linux/completion.h>
> +#include <linux/freezer.h>
> +#include <linux/uaccess.h>
> +#include <linux/io.h>
> +#include <linux/can/platform/mcp251x.h>
> +
> +/* SPI interface instruction set */
> +#define INSTRUCTION_WRITE	0x02
> +#define INSTRUCTION_READ	0x03
> +#define INSTRUCTION_BIT_MODIFY	0x05
> +#define INSTRUCTION_LOAD_TXB(n)	(0x40 + 2 * (n))
> +#define INSTRUCTION_READ_RXB(n)	(((n) == 0) ? 0x90 : 0x94)
> +#define INSTRUCTION_RESET	0xC0
> +
> +/* MPC251x registers */
> +#define CANSTAT	      0x0e
> +#define CANCTRL	      0x0f
> +#  define CANCTRL_REQOP_MASK	    0xe0
> +#  define CANCTRL_REQOP_CONF	    0x80
> +#  define CANCTRL_REQOP_LISTEN_ONLY 0x60
> +#  define CANCTRL_REQOP_LOOPBACK    0x40
> +#  define CANCTRL_REQOP_SLEEP	    0x20
> +#  define CANCTRL_REQOP_NORMAL	    0x00
> +#  define CANCTRL_OSM		    0x08
> +#  define CANCTRL_ABAT		    0x10
> +#define TEC	      0x1c
> +#define REC	      0x1d
> +#define CNF1	      0x2a
> +#  define CNF1_SJW_SHIFT   6
> +#define CNF2	      0x29
> +#  define CNF2_BTLMODE	   0x80
> +#  define CNF2_SAM         0x40
> +#  define CNF2_PS1_SHIFT   3
> +#define CNF3	      0x28
> +#  define CNF3_SOF	   0x08
> +#  define CNF3_WAKFIL	   0x04
> +#  define CNF3_PHSEG2_MASK 0x07
> +#define CANINTE	      0x2b
> +#  define CANINTE_MERRE 0x80
> +#  define CANINTE_WAKIE 0x40
> +#  define CANINTE_ERRIE 0x20
> +#  define CANINTE_TX2IE 0x10
> +#  define CANINTE_TX1IE 0x08
> +#  define CANINTE_TX0IE 0x04
> +#  define CANINTE_RX1IE 0x02
> +#  define CANINTE_RX0IE 0x01
> +#define CANINTF	      0x2c
> +#  define CANINTF_MERRF 0x80
> +#  define CANINTF_WAKIF 0x40
> +#  define CANINTF_ERRIF 0x20
> +#  define CANINTF_TX2IF 0x10
> +#  define CANINTF_TX1IF 0x08
> +#  define CANINTF_TX0IF 0x04
> +#  define CANINTF_RX1IF 0x02
> +#  define CANINTF_RX0IF 0x01
> +#define EFLG	      0x2d
> +#  define EFLG_EWARN	0x01
> +#  define EFLG_RXWAR	0x02
> +#  define EFLG_TXWAR	0x04
> +#  define EFLG_RXEP	0x08
> +#  define EFLG_TXEP	0x10
> +#  define EFLG_TXBO	0x20
> +#  define EFLG_RX0OVR	0x40
> +#  define EFLG_RX1OVR	0x80
> +#define TXBCTRL(n)  ((n * 0x10) + 0x30)

Please put brackets around "n": (((n) * 0x10) + 0x30)
Also the proper offset definition should be used.

#define TXBCTRL(n)  (((n) * 0x10) + 0x30 + TXBCTRL_OFF)

Here and in similar cases below.

> +#  define TXBCTRL_ABTF	0x40
> +#  define TXBCTRL_MLOA	0x20
> +#  define TXBCTRL_TXERR 0x10
> +#  define TXBCTRL_TXREQ 0x08
> +#define TXBSIDH(n)  ((n * 0x10) + 0x31)
> +#  define SIDH_SHIFT    3
> +#define TXBSIDL(n)  ((n * 0x10) + 0x32)
> +#  define SIDL_SID_MASK    7
> +#  define SIDL_SID_SHIFT   5
> +#  define SIDL_EXIDE_SHIFT 3
> +#  define SIDL_EID_SHIFT   16
> +#  define SIDL_EID_MASK    3
> +#define TXBEID8(n)  ((n * 0x10) + 0x33)
> +#define TXBEID0(n)  ((n * 0x10) + 0x34)
> +#define TXBDLC(n)   ((n * 0x10) + 0x35)
> +#  define DLC_RTR_SHIFT    6
> +#define TXBCTRL_OFF 0
> +#define TXBSIDH_OFF 1
> +#define TXBSIDL_OFF 2
> +#define TXBEID8_OFF 3
> +#define TXBEID0_OFF 4
> +#define TXBDLC_OFF  5
> +#define TXBDAT_OFF  6
> +#define RXBCTRL(n)  ((n * 0x10) + 0x60)
> +#  define RXBCTRL_BUKT	0x04
> +#  define RXBCTRL_RXM0	0x20
> +#  define RXBCTRL_RXM1	0x40
> +#define RXBSIDH(n)  ((n * 0x10) + 0x61)
> +#  define RXBSIDH_SHIFT 3
> +#define RXBSIDL(n)  ((n * 0x10) + 0x62)
> +#  define RXBSIDL_IDE   0x08
> +#  define RXBSIDL_EID   3
> +#  define RXBSIDL_SHIFT 5
> +#define RXBEID8(n)  ((n * 0x10) + 0x63)
> +#define RXBEID0(n)  ((n * 0x10) + 0x64)
> +#define RXBDLC(n)   ((n * 0x10) + 0x65)
> +#  define RXBDLC_LEN_MASK  0x0f
> +#  define RXBDLC_RTR       0x40
> +#define RXBCTRL_OFF 0
> +#define RXBSIDH_OFF 1
> +#define RXBSIDL_OFF 2
> +#define RXBEID8_OFF 3
> +#define RXBEID0_OFF 4
> +#define RXBDLC_OFF  5
> +#define RXBDAT_OFF  6

I was thinking to use structure(s) for the offsets (register layout)
above, but fiddling with offsetof() does probably not make the code more
readable.

> +
> +#define GET_BYTE(val, byte)			\
> +	(((val) >> ((byte) * 8)) & 0xff)
> +#define SET_BYTE(val, byte)			\
> +	(((val) & 0xff) << ((byte) * 8))
> +
> +/*
> + * Buffer size required for the largest SPI transfer (i.e., reading a
> + * frame)
> + */
> +#define CAN_FRAME_MAX_DATA_LEN	8
> +#define SPI_TRANSFER_BUF_LEN	(6 + CAN_FRAME_MAX_DATA_LEN)
> +#define CAN_FRAME_MAX_BITS	128
> +
> +#define TX_ECHO_SKB_MAX	1
> +
> +#define DEVICE_NAME "mcp251x"
> +
> +static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */
> +module_param(mcp251x_enable_dma, int, S_IRUGO);
> +MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)");
> +
> +static struct can_bittiming_const mcp251x_bittiming_const = {
> +	.name = DEVICE_NAME,
> +	.tseg1_min = 3,
> +	.tseg1_max = 16,
> +	.tseg2_min = 2,
> +	.tseg2_max = 8,
> +	.sjw_max = 4,
> +	.brp_min = 1,
> +	.brp_max = 64,
> +	.brp_inc = 1,
> +};
> +
> +struct mcp251x_priv {
> +	struct can_priv	   can;
> +	struct net_device *net;
> +	struct spi_device *spi;
> +
> +	struct mutex spi_lock; /* SPI buffer lock */
> +	u8 *spi_tx_buf;
> +	u8 *spi_rx_buf;
> +	dma_addr_t spi_tx_dma;
> +	dma_addr_t spi_rx_dma;
> +
> +	struct sk_buff *tx_skb;
> +	int tx_len;
> +	struct workqueue_struct *wq;
> +	struct work_struct tx_work;
> +	struct work_struct irq_work;
> +	struct completion awake;
> +	int wake;
> +	int force_quit;
> +	int after_suspend;
> +#define AFTER_SUSPEND_UP 1
> +#define AFTER_SUSPEND_DOWN 2
> +#define AFTER_SUSPEND_POWER 4
> +#define AFTER_SUSPEND_RESTART 8
> +	int restart_tx;
> +};
> +
> +static void mcp251x_clean(struct net_device *net)
> +{
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +
> +	net->stats.tx_errors++;
> +	if (priv->tx_skb)
> +		dev_kfree_skb(priv->tx_skb);
> +	if (priv->tx_len)
> +		can_free_echo_skb(priv->net, 0);
> +	priv->tx_skb = NULL;
> +	priv->tx_len = 0;
> +}
> +
> +/*
> + * Note about handling of error return of mcp251x_spi_trans: accessing
> + * registers via SPI is not really different conceptually than using
> + * normal I/O assembler instructions, although it's much more
> + * complicated from a practical POV. So it's not advisable to always
> + * check the return value of this function. Imagine that every
> + * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
> + * error();", it would be a great mess (well there are some situation
> + * when exception handling C++ like could be useful after all). So we
> + * just check that transfers are OK at the beginning of our
> + * conversation with the chip and to avoid doing really nasty things
> + * (like injecting bogus packets in the network stack).
> + */
> +static int mcp251x_spi_trans(struct spi_device *spi, int len)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	struct spi_transfer t = {
> +		.tx_buf = priv->spi_tx_buf,
> +		.rx_buf = priv->spi_rx_buf,
> +		.len = len,
> +		.cs_change = 0,
> +	};
> +	struct spi_message m;
> +	int ret;
> +
> +	spi_message_init(&m);
> +
> +	if (mcp251x_enable_dma) {
> +		t.tx_dma = priv->spi_tx_dma;
> +		t.rx_dma = priv->spi_rx_dma;
> +		m.is_dma_mapped = 1;
> +	}
> +
> +	spi_message_add_tail(&t, &m);
> +
> +	ret = spi_sync(spi, &m);
> +	if (ret < 0)

if (ret) ?

> +		dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret);
> +	return ret;
> +}
> +
> +static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	u8 val = 0;
> +
> +	mutex_lock(&priv->spi_lock);
> +
> +	priv->spi_tx_buf[0] = INSTRUCTION_READ;
> +	priv->spi_tx_buf[1] = reg;
> +
> +	mcp251x_spi_trans(spi, 3);
> +	val = priv->spi_rx_buf[2];
> +
> +	mutex_unlock(&priv->spi_lock);
> +
> +	return val;
> +}
> +
> +static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +
> +	mutex_lock(&priv->spi_lock);
> +
> +	priv->spi_tx_buf[0] = INSTRUCTION_WRITE;
> +	priv->spi_tx_buf[1] = reg;
> +	priv->spi_tx_buf[2] = val;
> +
> +	mcp251x_spi_trans(spi, 3);
> +
> +	mutex_unlock(&priv->spi_lock);
> +}
> +
> +static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
> +			       u8 mask, uint8_t val)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +
> +	mutex_lock(&priv->spi_lock);
> +
> +	priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY;
> +	priv->spi_tx_buf[1] = reg;
> +	priv->spi_tx_buf[2] = mask;
> +	priv->spi_tx_buf[3] = val;
> +
> +	mcp251x_spi_trans(spi, 4);
> +
> +	mutex_unlock(&priv->spi_lock);
> +}
> +
> +static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *data,

s/data/buf/ to avoid confusion with the CAN payload data.

> +				int len, int tx_buf_idx)
> +{
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +
> +	if (pdata->model == CAN_MCP251X_MCP2510) {
> +		int i;
> +
> +		for (i = 1; i < TXBDAT_OFF + len; i++)
> +			mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i,
> +					  data[i]);
> +	} else {
> +		mutex_lock(&priv->spi_lock);
> +		memcpy(priv->spi_tx_buf, data, TXBDAT_OFF + len);
> +		mcp251x_spi_trans(spi, TXBDAT_OFF + len);
> +		mutex_unlock(&priv->spi_lock);
> +	}
> +}
> +
> +static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
> +			  int tx_buf_idx)
> +{
> +	u32 sid, eid, exide, rtr;
> +	u8 buf[SPI_TRANSFER_BUF_LEN];
> +
> +	exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */
> +	if (exide)
> +		sid = (frame->can_id & CAN_EFF_MASK) >> 18;
> +	else
> +		sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */
> +	eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */
> +	rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* Remote transmission */
> +
> +	buf[TXBCTRL_OFF] = INSTRUCTION_LOAD_TXB(tx_buf_idx);
> +	buf[TXBSIDH_OFF] = sid >> SIDH_SHIFT;
> +	buf[TXBSIDL_OFF] = ((sid & SIDL_SID_MASK) << SIDL_SID_SHIFT) |
> +		(exide << SIDL_EXIDE_SHIFT) |
> +		((eid >> SIDL_EID_SHIFT) & SIDL_EID_MASK);
> +	buf[TXBEID8_OFF] = GET_BYTE(eid, 1);
> +	buf[TXBEID0_OFF] = GET_BYTE(eid, 0);
> +	buf[TXBDLC_OFF]  = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;

Maybe you understand now my comment about using structs, e.g. for buf,
at the beginning.

> +	memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
> +	mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
> +	mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
> +}
> +
> +static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *data,

s/data/buf/, see above.

> +				int buf_idx)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +
> +	if (pdata->model == CAN_MCP251X_MCP2510) {
> +		int i, len;
> +
> +		for (i = 1; i < RXBDAT_OFF; i++)
> +			data[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i);
> +		len = data[RXBDLC_OFF] & RXBDLC_LEN_MASK;
> +		if (len > 8)
> +			len = 8;
> +		for (; i < (RXBDAT_OFF + len); i++)
> +			data[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i);
> +	} else {
> +		mutex_lock(&priv->spi_lock);
> +
> +		priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx);
> +		mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN);
> +		memcpy(data, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN);
> +
> +		mutex_unlock(&priv->spi_lock);
> +	}
> +}
> +
> +static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	struct sk_buff *skb;
> +	struct can_frame *frame;
> +	u8 buf[SPI_TRANSFER_BUF_LEN];
> +
> +	skb = alloc_can_skb(priv->net, &frame);
> +	if (!skb) {
> +		dev_err(&spi->dev, "cannot allocate RX skb\n");
> +		priv->net->stats.rx_dropped++;
> +		return;
> +	}
> +
> +	mcp251x_hw_rx_frame(spi, buf, buf_idx);
> +	if (buf[RXBSIDL_OFF] & RXBSIDL_IDE) {
> +		/* Extended ID format */
> +		frame->can_id = CAN_EFF_FLAG;
> +		frame->can_id |=
> +			/* Extended ID part */
> +			SET_BYTE(buf[RXBSIDL_OFF] & RXBSIDL_EID, 2) |
> +			SET_BYTE(buf[RXBEID8_OFF],               1) |
> +			SET_BYTE(buf[RXBEID0_OFF],               0) |

Please don't align arguments or variables.

> +			/* Standard ID part */
> +			(((buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) |
> +			  (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT)) << 18);
> +		if (buf[RXBDLC_OFF] & RXBDLC_RTR) {
> +			/* Remote transmission request */
> +			frame->can_id |= CAN_RTR_FLAG;
> +		}

Remove {}, please.

> +	} else
> +		/* Standard ID format */
> +		frame->can_id =
> +			(buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) |
> +			(buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT);

Please use {} here as well.

> +	/* Data length */
> +	frame->can_dlc = buf[RXBDLC_OFF] & RXBDLC_LEN_MASK;
> +	if (frame->can_dlc > 8) {
> +		dev_warn(&spi->dev, "invalid frame recevied\n");
> +		priv->net->stats.rx_errors++;
> +		dev_kfree_skb(skb);
> +		return;
> +	}
> +	memcpy(frame->data, buf + RXBDAT_OFF, frame->can_dlc);
> +
> +	priv->net->stats.rx_packets++;
> +	priv->net->stats.rx_bytes += frame->can_dlc;
> +	netif_rx(skb);
> +}
> +
> +static void mcp251x_hw_sleep(struct spi_device *spi)
> +{
> +	mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
> +}
> +
> +static void mcp251x_hw_wakeup(struct spi_device *spi)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +
> +	priv->wake = 1;
> +
> +	/* Can only wake up by generating a wake-up interrupt. */
> +	mcp251x_write_bits(spi, CANINTE, CANINTE_WAKIE, CANINTE_WAKIE);
> +	mcp251x_write_bits(spi, CANINTF, CANINTF_WAKIF, CANINTF_WAKIF);
> +
> +	/* Wait until the device is awake */
> +	if (!wait_for_completion_timeout(&priv->awake, HZ))
> +		dev_err(&spi->dev, "MCP251x didn't wake-up\n");
> +}
> +
> +static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
> +					   struct net_device *net)
> +{
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +	struct spi_device *spi = priv->spi;
> +
> +	if (priv->tx_skb || priv->tx_len) {
> +		dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
> +		netif_stop_queue(net);
> +		return NETDEV_TX_BUSY;
> +	}
> +
> +	if (skb->len != sizeof(struct can_frame)) {
> +		dev_err(&spi->dev, "dropping packet - bad length\n");
> +		dev_kfree_skb(skb);
> +		net->stats.tx_dropped++;
> +		return 0;

return NETDEV_TX_OK; ?

> +	}
> +
> +	netif_stop_queue(net);
> +	priv->tx_skb = skb;
> +	net->trans_start = jiffies;
> +	queue_work(priv->wq, &priv->tx_work);
> +
> +	return NETDEV_TX_OK;
> +}
> +
> +static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode)
> +{
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +
> +	switch (mode) {
> +	case CAN_MODE_START:
> +		/* We have to delay work since SPI I/O may sleep */
> +		priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +		priv->restart_tx = 1;
> +		if (priv->can.restart_ms == 0)
> +			priv->after_suspend = AFTER_SUSPEND_RESTART;
> +		queue_work(priv->wq, &priv->irq_work);
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
> +static void mcp251x_set_normal_mode(struct spi_device *spi)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	unsigned long timeout;
> +
> +	/* Enable interrupts */
> +	mcp251x_write_reg(spi, CANINTE,
> +			  CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE |
> +			  CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE |
> +			  CANINTF_MERRF);
> +
> +	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
> +		/* Put device into loopback mode */
> +		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);

Please use brackets here as well. See:

http://lxr.linux.no/#linux+v2.6.31/Documentation/CodingStyle#L171

> +	else {
> +		/* Put device into normal mode */
> +		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
> +
> +		/* Wait for the device to enter normal mode */
> +		timeout = jiffies + HZ;
> +		while (mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) {
> +			schedule();
> +			if (time_after(jiffies, timeout)) {
> +				dev_err(&spi->dev, "MCP251x didn't"
> +					" enter in normal mode\n");
> +				return;
> +			}
> +		}
> +	}
> +	priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +}
> +
> +static int mcp251x_do_set_bittiming(struct net_device *net)
> +{
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +	struct can_bittiming *bt = &priv->can.bittiming;
> +	struct spi_device *spi = priv->spi;
> +	u8 state;
> +
> +	/* Store original mode and set mode to config */

Do you need that. The bit-timing can only be set when the device is
stopped (down).

> +	state = mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK;
> +	mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK,
> +			   CANCTRL_REQOP_CONF);
> +
> +	mcp251x_write_reg(spi, CNF1, ((bt->sjw - 1) << CNF1_SJW_SHIFT) |
> +			  (bt->brp - 1));
> +	mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE |
> +			  (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ?
> +			   CNF2_SAM : 0) |
> +			  ((bt->phase_seg1 - 1) << CNF2_PS1_SHIFT) |
> +			  (bt->prop_seg - 1));
> +	mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK,
> +			   (bt->phase_seg2 - 1));
> +	dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n",
> +		 mcp251x_read_reg(spi, CNF1),
> +		 mcp251x_read_reg(spi, CNF2),
> +		 mcp251x_read_reg(spi, CNF3));
> +	/* Restore original state */
> +	mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, state);
> +
> +	return 0;
> +}
> +
> +static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,
> +			 struct spi_device *spi)
> +{
> +	int ret;
> +
> +	ret = open_candev(net);
> +	if (ret) {
> +		dev_err(&spi->dev, "unable to set initial baudrate!\n");
> +		return ret;
> +	}
> +
> +	/* Enable RX0->RX1 buffer roll over and disable filters */
> +	mcp251x_write_bits(spi, RXBCTRL(0),
> +			   RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1,
> +			   RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1);
> +	mcp251x_write_bits(spi, RXBCTRL(1),
> +			   RXBCTRL_RXM0 | RXBCTRL_RXM1,
> +			   RXBCTRL_RXM0 | RXBCTRL_RXM1);
> +	return 0;
> +}
> +
> +static void mcp251x_hw_reset(struct spi_device *spi)
> +{
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	int ret;
> +
> +	mutex_lock(&priv->spi_lock);
> +
> +	priv->spi_tx_buf[0] = INSTRUCTION_RESET;
> +
> +	ret = spi_write(spi, priv->spi_tx_buf, 1);
> +
> +	mutex_unlock(&priv->spi_lock);
> +
> +	if (ret < 0)

if (ret) ?

> +		dev_err(&spi->dev, "reset failed: ret = %d\n", ret);
> +	/* Wait for reset to finish */
> +	mdelay(10);
> +}
> +
> +static int mcp251x_hw_probe(struct spi_device *spi)
> +{
> +	int st1, st2;
> +
> +	mcp251x_hw_reset(spi);
> +
> +	/*
> +	 * Please note that these are "magic values" based on after
> +	 * reset defaults taken from data sheet which allows us to see
> +	 * if we really have a chip on the bus (we avoid common all
> +	 * zeroes or all ones situations)
> +	 */
> +	st1 = mcp251x_read_reg(spi, CANSTAT) & 0xEE;
> +	st2 = mcp251x_read_reg(spi, CANCTRL) & 0x17;
> +
> +	dev_dbg(&spi->dev, "CANSTAT 0x%02x CANCTRL 0x%02x\n", st1, st2);
> +
> +	/* Check for power up default values */
> +	return (st1 == 0x80 && st2 == 0x07) ? 1 : 0;
> +}
> +
> +static irqreturn_t mcp251x_can_isr(int irq, void *dev_id)
> +{
> +	struct net_device *net = (struct net_device *)dev_id;
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +
> +	/* Schedule bottom half */
> +	if (!work_pending(&priv->irq_work))
> +		queue_work(priv->wq, &priv->irq_work);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int mcp251x_open(struct net_device *net)
> +{
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +	struct spi_device *spi = priv->spi;
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +	int ret;
> +
> +	if (pdata->transceiver_enable)
> +		pdata->transceiver_enable(1);
> +
> +	priv->force_quit = 0;
> +	priv->tx_skb = NULL;
> +	priv->tx_len = 0;
> +
> +	ret = request_irq(spi->irq, mcp251x_can_isr,
> +			  IRQF_TRIGGER_FALLING, DEVICE_NAME, net);
> +	if (ret < 0) {

"if (ret)" ?

> +		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
> +		return ret;
> +	}
> +
> +	mcp251x_hw_wakeup(spi);
> +	mcp251x_hw_reset(spi);
> +	ret = mcp251x_setup(net, priv, spi);
> +	if (ret < 0) {

"if (ret)" ?

> +		disable_irq(spi->irq);

free_irq? And what about the transeiver? The usual goto cleanup method
would make sense here.

> +		return ret;
> +	}
> +	mcp251x_set_normal_mode(spi);
> +	netif_wake_queue(net);
> +
> +	return 0;
> +}
> +
> +static int mcp251x_stop(struct net_device *net)
> +{
> +	struct mcp251x_priv *priv = netdev_priv(net);
> +	struct spi_device *spi = priv->spi;
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +
> +	/* Disable and clear pending interrupts */
> +	mcp251x_write_reg(spi, CANINTE, 0x00);
> +	mcp251x_write_reg(spi, CANINTF, 0x00);
> +
> +	priv->force_quit = 1;
> +	disable_irq(spi->irq);

Why not freeing the irq already here?

> +	flush_workqueue(priv->wq);
> +
> +	mcp251x_write_reg(spi, TXBCTRL(0), 0);

Hm, but you still need the interrupt!?

> +	if (priv->tx_skb || priv->tx_len)
> +		mcp251x_clean(net);
> +
> +	mcp251x_hw_sleep(spi);
> +
> +	free_irq(spi->irq, net);
> +
> +	if (pdata->transceiver_enable)
> +		pdata->transceiver_enable(0);
> +
> +	priv->can.state = CAN_STATE_STOPPED;
> +	close_candev(net);

You should call close_candev early to cancel the buf-off recovery timer.

> +	return 0;
> +}
> +
> +static void mcp251x_tx_work_handler(struct work_struct *ws)
> +{
> +	struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv,
> +						 tx_work);
> +	struct spi_device *spi = priv->spi;
> +	struct net_device *net = priv->net;
> +	struct can_frame *frame;
> +
> +	if (priv->tx_skb) {
> +		frame = (struct can_frame *)priv->tx_skb->data;
> +
> +		if (priv->can.state == CAN_STATE_BUS_OFF) {
> +			mcp251x_clean(net);
> +			netif_wake_queue(net);
> +			return;
> +		}
> +		if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
> +			frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
> +		mcp251x_hw_tx(spi, frame, 0);
> +		priv->tx_len = 1 + frame->can_dlc;
> +		can_put_echo_skb(priv->tx_skb, net, 0);
> +		priv->tx_skb = NULL;
> +	}
> +}
> +
> +static void mcp251x_irq_work_handler(struct work_struct *ws)
> +{
> +	struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv,
> +						 irq_work);
> +	struct spi_device *spi = priv->spi;
> +	struct net_device *net = priv->net;
> +	u8 txbnctrl;
> +	u8 intf;
> +	enum can_state new_state;
> +
> +	if (priv->after_suspend) {
> +		mdelay(10);
> +		mcp251x_hw_reset(spi);
> +		mcp251x_setup(net, priv, spi);
> +		if (priv->after_suspend & AFTER_SUSPEND_RESTART)
> +			mcp251x_set_normal_mode(spi);

Please use {} here as well.

> +		else if (priv->after_suspend & AFTER_SUSPEND_UP) {
> +			netif_device_attach(net);
> +			/* Clean since we lost tx buffer */
> +			if (priv->tx_skb || priv->tx_len) {
> +				mcp251x_clean(net);
> +				netif_wake_queue(net);
> +			}
> +			mcp251x_set_normal_mode(spi);
> +		} else
> +			mcp251x_hw_sleep(spi);

Please use {} here as well.

> +		priv->after_suspend = 0;
> +	}
> +
> +	if (priv->can.restart_ms == 0 && priv->can.state == CAN_STATE_BUS_OFF) {
> +		while (!priv->force_quit && !freezing(current) &&
> +		       (intf = mcp251x_read_reg(spi, CANINTF)))
> +			mcp251x_write_bits(spi, CANINTF, intf, 0x00);
> +		return;
> +	}
> +
> +	while (!priv->force_quit && !freezing(current)) {
> +		u8 eflag = mcp251x_read_reg(spi, EFLG);
> +		int can_id = 0, data1 = 0;
> +
> +		mcp251x_write_reg(spi, EFLG, 0x00);
> +
> +		if (priv->restart_tx) {
> +			priv->restart_tx = 0;
> +			mcp251x_write_reg(spi, TXBCTRL(0), 0);
> +			if (priv->tx_skb || priv->tx_len)
> +				mcp251x_clean(net);
> +			netif_wake_queue(net);
> +			can_id |= CAN_ERR_RESTARTED;
> +		}
> +
> +		if (priv->wake) {
> +			/* Wait whilst the device wakes up */
> +			mdelay(10);
> +			priv->wake = 0;
> +		}
> +
> +		intf = mcp251x_read_reg(spi, CANINTF);
> +		mcp251x_write_bits(spi, CANINTF, intf, 0x00);
> +
> +		/* Update can state */
> +		if (eflag & EFLG_TXBO) {
> +			new_state = CAN_STATE_BUS_OFF;
> +			can_id |= CAN_ERR_BUSOFF;
> +		} else if (eflag & EFLG_TXEP) {
> +			new_state = CAN_STATE_ERROR_PASSIVE;
> +			can_id |= CAN_ERR_CRTL;
> +			data1 |= CAN_ERR_CRTL_TX_PASSIVE;
> +		} else if (eflag & EFLG_RXEP) {
> +			new_state = CAN_STATE_ERROR_PASSIVE;
> +			can_id |= CAN_ERR_CRTL;
> +			data1 |= CAN_ERR_CRTL_RX_PASSIVE;
> +		} else if (eflag & EFLG_TXWAR) {
> +			new_state = CAN_STATE_ERROR_WARNING;
> +			can_id |= CAN_ERR_CRTL;
> +			data1 |= CAN_ERR_CRTL_TX_WARNING;
> +		} else if (eflag & EFLG_RXWAR) {
> +			new_state = CAN_STATE_ERROR_WARNING;
> +			can_id |= CAN_ERR_CRTL;
> +			data1 |= CAN_ERR_CRTL_RX_WARNING;
> +		} else
> +			new_state = CAN_STATE_ERROR_ACTIVE;

Please use {} here as well.

> +
> +		/* Update can state statistics */
> +		switch (priv->can.state) {
> +		case CAN_STATE_ERROR_ACTIVE:
> +			if (new_state >= CAN_STATE_ERROR_WARNING &&
> +			    new_state <= CAN_STATE_BUS_OFF)
> +				priv->can.can_stats.error_warning++;
> +		case CAN_STATE_ERROR_WARNING:	/* fallthrough */
> +			if (new_state >= CAN_STATE_ERROR_PASSIVE &&
> +			    new_state <= CAN_STATE_BUS_OFF)
> +				priv->can.can_stats.error_passive++;
> +			break;
> +		default:
> +			break;
> +		}
> +		priv->can.state = new_state;
> +
> +		if ((intf & CANINTF_ERRIF) || (can_id & CAN_ERR_RESTARTED)) {
> +			struct sk_buff *skb;
> +			struct can_frame *frame;
> +
> +			/* Create error frame */
> +			skb = alloc_can_err_skb(net, &frame);
> +			if (skb) {
> +				/* Set error frame flags based on bus state */
> +				frame->can_id = can_id;
> +				frame->data[1] = data1;
> +
> +				/* Update net stats for overflows */
> +				if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) {
> +					if (eflag & EFLG_RX0OVR)
> +						net->stats.rx_over_errors++;
> +					if (eflag & EFLG_RX1OVR)
> +						net->stats.rx_over_errors++;
> +					frame->can_id |= CAN_ERR_CRTL;
> +					frame->data[1] |=
> +						CAN_ERR_CRTL_RX_OVERFLOW;
> +				}
> +
> +				netif_rx(skb);
> +			} else
> +				dev_info(&spi->dev,
> +					 "cannot allocate error skb\n");

Please use {} here as well.

> +		}
> +
> +		if (priv->can.state == CAN_STATE_BUS_OFF) {
> +			if (priv->can.restart_ms == 0) {
> +				can_bus_off(net);
> +				mcp251x_hw_sleep(spi);
> +				return;
> +			}
> +		}
> +
> +		if (intf == 0)
> +			break;
> +
> +		if (intf & CANINTF_WAKIF)
> +			complete(&priv->awake);
> +
> +		if (intf & CANINTF_MERRF) {
> +			/* If there are pending Tx buffers, restart queue */
> +			txbnctrl = mcp251x_read_reg(spi, TXBCTRL(0));
> +			if (!(txbnctrl & TXBCTRL_TXREQ)) {
> +				if (priv->tx_skb || priv->tx_len)
> +					mcp251x_clean(net);
> +				netif_wake_queue(net);
> +			}
> +		}
> +
> +		if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) {
> +			net->stats.tx_packets++;
> +			net->stats.tx_bytes += priv->tx_len - 1;
> +			if (priv->tx_len) {
> +				can_get_echo_skb(net, 0);
> +				priv->tx_len = 0;
> +			}
> +			netif_wake_queue(net);
> +		}
> +
> +		if (intf & CANINTF_RX0IF)
> +			mcp251x_hw_rx(spi, 0);
> +
> +		if (intf & CANINTF_RX1IF)
> +			mcp251x_hw_rx(spi, 1);
> +	}
> +}
> +
> +static const struct net_device_ops mcp251x_netdev_ops = {
> +	.ndo_open	= mcp251x_open,
> +	.ndo_stop	= mcp251x_stop,
> +	.ndo_start_xmit	= mcp251x_hard_start_xmit,
> +};
> +
> +static struct net_device
> +*alloc_mcp251x_netdev(int sizeof_priv,
> +		      struct mcp251x_platform_data *pdata)

Add __devinit or, even better, put the code into mcp251x_can_probe?

> +{
> +	struct net_device *net;
> +	struct mcp251x_priv *priv;
> +
> +	net = alloc_candev(sizeof_priv, TX_ECHO_SKB_MAX);
> +	if (!net)
> +		return NULL;
> +
> +	priv = netdev_priv(net);
> +
> +	net->netdev_ops		= &mcp251x_netdev_ops;
> +	net->flags		|= IFF_ECHO;
> +
> +	priv->can.bittiming_const = &mcp251x_bittiming_const;
> +	priv->can.do_set_mode	  = mcp251x_do_set_mode;
> +	priv->can.clock.freq      = pdata->oscillator_frequency / 2;
> +	priv->can.do_set_bittiming	= mcp251x_do_set_bittiming;

Don't align expressions. Use just *one* space before and after "=".

> +
> +	priv->net = net;
> +
> +	return net;
> +}
> +
> +static int __devinit mcp251x_can_probe(struct spi_device *spi)
> +{
> +	struct net_device *net;
> +	struct mcp251x_priv *priv;
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +	int ret = -ENODEV;
> +
> +	if (!pdata)
> +		/* Platform data is required for osc freq */
> +		goto error_out;
> +
> +	/* Allocate can/net device */
> +	net = alloc_mcp251x_netdev(sizeof(struct mcp251x_priv), pdata);
> +	if (!net) {
> +		ret = -ENOMEM;
> +		goto error_alloc;
> +	}
> +
> +	priv = netdev_priv(net);
> +	dev_set_drvdata(&spi->dev, priv);
> +
> +	priv->spi = spi;
> +	mutex_init(&priv->spi_lock);
> +
> +	/* If requested, allocate DMA buffers */
> +	if (mcp251x_enable_dma) {
> +		spi->dev.coherent_dma_mask = ~0;
> +
> +		/*
> +		 * Minimum coherent DMA allocation is PAGE_SIZE, so allocate
> +		 * that much and share it between Tx and Rx DMA buffers.
> +		 */
> +		priv->spi_tx_buf = dma_alloc_coherent(&spi->dev,
> +						      PAGE_SIZE,
> +						      &priv->spi_tx_dma,
> +						      GFP_DMA);
> +
> +		if (priv->spi_tx_buf) {
> +			priv->spi_rx_buf = (u8 *)(priv->spi_tx_buf +
> +						  (PAGE_SIZE / 2));
> +			priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
> +							(PAGE_SIZE / 2));
> +		} else
> +			/* Fall back to non-DMA */
> +			mcp251x_enable_dma = 0;

Please use {} here as well.

> +	}
> +
> +	/* Allocate non-DMA buffers */
> +	if (!mcp251x_enable_dma) {
> +		priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
> +		if (!priv->spi_tx_buf) {
> +			ret = -ENOMEM;
> +			goto error_tx_buf;
> +		}
> +		priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
> +		if (!priv->spi_tx_buf) {
> +			ret = -ENOMEM;
> +			goto error_rx_buf;
> +		}
> +	}
> +
> +	if (pdata->power_enable)
> +		pdata->power_enable(1);
> +
> +	/* Call out to platform specific setup */
> +	if (pdata->board_specific_setup)
> +		pdata->board_specific_setup(spi);
> +
> +	SET_NETDEV_DEV(net, &spi->dev);
> +
> +	priv->wq = create_freezeable_workqueue("mcp251x_wq");
> +
> +	INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
> +	INIT_WORK(&priv->irq_work, mcp251x_irq_work_handler);
> +
> +	init_completion(&priv->awake);
> +
> +	/* Configure the SPI bus */
> +	spi->mode = SPI_MODE_0;
> +	spi->bits_per_word = 8;
> +	spi_setup(spi);
> +
> +	if (!mcp251x_hw_probe(spi)) {
> +		dev_info(&spi->dev, "Probe failed\n");
> +		goto error_probe;
> +	}
> +	mcp251x_hw_sleep(spi);
> +
> +	if (pdata->transceiver_enable)
> +		pdata->transceiver_enable(0);
> +
> +	ret = register_candev(net);
> +	if (ret >= 0) {
> +		dev_info(&spi->dev, "probed\n");
> +		return ret;
> +	}
> +error_probe:
> +	if (!mcp251x_enable_dma)
> +		kfree(priv->spi_rx_buf);
> +error_rx_buf:
> +	if (!mcp251x_enable_dma)
> +		kfree(priv->spi_tx_buf);
> +error_tx_buf:
> +	free_candev(net);
> +	if (mcp251x_enable_dma)
> +		dma_free_coherent(&spi->dev, PAGE_SIZE,
> +				  priv->spi_tx_buf, priv->spi_tx_dma);
> +error_alloc:
> +	dev_err(&spi->dev, "probe failed\n");
> +error_out:
> +	return ret;
> +}
> +
> +static int __devexit mcp251x_can_remove(struct spi_device *spi)
> +{
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	struct net_device *net = priv->net;
> +
> +	unregister_candev(net);
> +	free_candev(net);
> +
> +	priv->force_quit = 1;
> +	flush_workqueue(priv->wq);
> +	destroy_workqueue(priv->wq);
> +
> +	if (mcp251x_enable_dma)
> +		dma_free_coherent(&spi->dev, PAGE_SIZE,
> +				  priv->spi_tx_buf, priv->spi_tx_dma);

Please use {} here as well.

> +	else {
> +		kfree(priv->spi_tx_buf);
> +		kfree(priv->spi_rx_buf);
> +	}
> +
> +	if (pdata->power_enable)
> +		pdata->power_enable(0);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
> +{
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +	struct net_device *net = priv->net;
> +
> +	if (netif_running(net)) {
> +		netif_device_detach(net);
> +
> +		mcp251x_hw_sleep(spi);
> +		if (pdata->transceiver_enable)
> +			pdata->transceiver_enable(0);
> +		priv->after_suspend = AFTER_SUSPEND_UP;
> +	} else
> +		priv->after_suspend = AFTER_SUSPEND_DOWN;

Please use {} here as well.

> +
> +	if (pdata->power_enable) {
> +		pdata->power_enable(0);
> +		priv->after_suspend |= AFTER_SUSPEND_POWER;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mcp251x_can_resume(struct spi_device *spi)
> +{
> +	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> +
> +	if (priv->after_suspend & AFTER_SUSPEND_POWER) {
> +		pdata->power_enable(1);
> +		queue_work(priv->wq, &priv->irq_work);
> +	} else {
> +		if (priv->after_suspend & AFTER_SUSPEND_UP) {
> +			if (pdata->transceiver_enable)
> +				pdata->transceiver_enable(1);
> +			queue_work(priv->wq, &priv->irq_work);
> +		} else
> +			priv->after_suspend = 0;

Please use {} here as well and check for similar cases. I might not have
spotted all.

> +	}
> +	return 0;
> +}
> +#else
> +#define mcp251x_can_suspend NULL
> +#define mcp251x_can_resume NULL
> +#endif
> +
> +static struct spi_driver mcp251x_can_driver = {
> +	.driver = {
> +		.name		= DEVICE_NAME,
> +		.bus		= &spi_bus_type,
> +		.owner		= THIS_MODULE,
> +	},
> +
> +	.probe		= mcp251x_can_probe,
> +	.remove		= __devexit_p(mcp251x_can_remove),
> +	.suspend	= mcp251x_can_suspend,
> +	.resume		= mcp251x_can_resume,

Use just *one* space before and after "=".

> +};
> +
> +static int __init mcp251x_can_init(void)
> +{
> +	return spi_register_driver(&mcp251x_can_driver);
> +}
> +
> +static void __exit mcp251x_can_exit(void)
> +{
> +	spi_unregister_driver(&mcp251x_can_driver);
> +}
> +
> +module_init(mcp251x_can_init);
> +module_exit(mcp251x_can_exit);
> +
> +MODULE_AUTHOR("Chris Elston <celston-Bm0nJX+W7e9BDgjK7y7TUQ@public.gmane.org>, "
> +	      "Christian Pellegrin <chripell-LERDrqjqfvZg9hUCZPvPmw@public.gmane.org>");
> +MODULE_DESCRIPTION("Microchip 251x CAN driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/can/platform/mcp251x.h b/include/linux/can/platform/mcp251x.h
> new file mode 100644
> index 0000000..d217ffa
> --- /dev/null
> +++ b/include/linux/can/platform/mcp251x.h
> @@ -0,0 +1,34 @@
> +#ifndef __CAN_PLATFORM_MCP251X_H__
> +#define __CAN_PLATFORM_MCP251X_H__
> +
> +/*
> + *
> + * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
> + *
> + */
> +
> +/**
> + * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
> + * @oscillator_frequency:       - oscillator frequency in Hz
> + * @model:                      - actual type of chip
> + * @board_specific_setup:       - called before probing the chip (power,reset)
> + * @transceiver_enable:         - called to power on/off the transceiver
> + * @power_enable:               - called to power on/off the mcp *and* the
> + *                                transceiver
> + *
> + * Please note that you should define power_enable or transceiver_enable or
> + * none of them. Defining both of them is no use.
> + *
> + */
> +
> +struct mcp251x_platform_data {
> +	unsigned long oscillator_frequency;
> +	int model;
> +#define CAN_MCP251X_MCP2510 0
> +#define CAN_MCP251X_MCP2515 1
> +	int (*board_specific_setup)(struct spi_device *spi);
> +	int (*transceiver_enable)(int enable);
> +	int (*power_enable) (int enable);
> +};
> +
> +#endif /* __CAN_PLATFORM_MCP251X_H__ */


Thanks,

Wolfgang.

^ permalink raw reply

* Re: [PATCH 2/8] param: use ops in struct kernel_param, rather than get and set fns directly
From: Takashi Iwai @ 2009-11-01 10:26 UTC (permalink / raw)
  To: Rusty Russell
  Cc: linux-kernel, David S. Miller, Ville Syrjala, Dmitry Torokhov,
	Alessandro Rubini, Michal Januszewski, Trond Myklebust,
	J. Bruce Fields, Neil Brown, linux-input, linux-fbdev-devel,
	linux-nfs, netdev
In-Reply-To: <200910302143.40268.rusty@rustcorp.com.au>

At Fri, 30 Oct 2009 21:43:39 +1030,
Rusty Russell wrote:
> 
> On Fri, 30 Oct 2009 08:48:12 pm Takashi Iwai wrote:
> > At Fri, 23 Oct 2009 00:51:28 +1030,
> > Rusty Russell wrote:
> > > 
> > > This is more kernel-ish, saves some space, and also allows us to
> > > expand the ops without breaking all the callers who are happy for the
> > > new members to be NULL.
> > > 
> > > The few places which defined their own param types are changed to the
> > > new scheme.
> > > 
> > > Since we're touching them anyway, we change get and set to take a
> > > const struct kernel_param (which they were, and will be again).
> > > 
> > > To reduce churn, module_param_call creates the ops struct so the callers
> > > don't have to change (and casts the functions to reduce warnings).
> > > The modern version which takes an ops struct is called module_param_cb.
> > 
> > This is nice, as it also reduces the size of struct kernel_param, so
> > each parameter uses less footprint (who cares, though?) :)
> > 
> > But, just wondering whether we still need to export get/set
> > functions.  They can be called from ops now, so if any, it can be
> > defined even as an inlinefunction or a macro.
> 
> My thought too, so I tried that, but many are still used like so:
> 
> 	module_param_call(foo, set_foo, param_get_uint, NULL, 0644);
> 
> They can all be replaced in time with something like:
> 	static int param_get_foo(char *buffer, const struct kernel_param *kp)
> 	{
> 		return param_ops_uint.get(buffer, kp);
> 	}
> 
> But it'll take a transition period.

Fair enough.  And, maybe these get/set should be defined as an ops
explicitly so that it can be used for multiple parameters.  But we
can do cleanups later, of course :)

Oh, in case you need,
	Reviewed-by: Takashi Iwai <tiwai@suse.de>
for all new patches.


Thanks!

Takashi

^ permalink raw reply

* Re: [net-next-2.6 PATCH RFC] TCPCT part 1d: generate Responder Cookie
From: William Allen Simpson @ 2009-11-01 13:01 UTC (permalink / raw)
  To: Linux Kernel Developers; +Cc: Linux Kernel Network Developers
In-Reply-To: <4AEAC763.4070200@gmail.com>

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

Since October 4th, I've repeatedly asked publicly for assistance with these
Linux-specific memory locking constructs and cryptography.  I've also sent
private messages.  No help has been forthcoming.  None.  Nada.

At this point, I've spent weeks re-spinning code that I'd understood was
approved a year ago.  The whole project should have been finished by now!

So, I'll try a larger audience.  Could somebody take a look at my usage of
read and write locking?

NB, I'm trying to port some 15-year-old fairly simple and straightforward
(single cpu) code from the KA9Q cooperative multitasking platform.

I've examined existing code used for syncookies and TCP MD5 authenticators.
Neither meets my needs, as this secret is updated every few minutes.  Both
have very different approaches.  They are rarely used.  My code will be
used on the order of tens of thousands of connections per second.

Moreover, it seems to my naive eye that the syncookie per cpu code simply
doesn't work properly.  The workspace is allocated per cpu, but the cpu
could change during the extensive SHA1 computations.  Bug?

Therefore, I'm approaching this as simply as possible.  I'm particularly
concerned about the initialization and cache state of memory pointers.

Does the locking handle this?  Or is there more to be done?


[-- Attachment #2: TCPCT+1d.patch --]
[-- Type: text/plain, Size: 7050 bytes --]

diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
index c118b2a..ec78a4b 100644
--- a/include/linux/cryptohash.h
+++ b/include/linux/cryptohash.h
@@ -2,6 +2,7 @@
 #define __CRYPTOHASH_H
 
 #define SHA_DIGEST_WORDS 5
+#define SHA_MESSAGE_BYTES (512 /*bits*/ / 8)
 #define SHA_WORKSPACE_WORDS 80
 
 void sha_init(__u32 *buf);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 51b7426..f669c43 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1526,12 +1526,18 @@ static inline int tcp_s_data_size(const struct tcp_sock *tp)
 		: 0;
 }
 
+/* Using SHA1 for now, define some constants.
+ */
+#define COOKIE_DIGEST_WORDS (SHA_DIGEST_WORDS)
+#define COOKIE_MESSAGE_WORDS (SHA_MESSAGE_BYTES / 4)
+#define COOKIE_WORKSPACE_WORDS (COOKIE_DIGEST_WORDS + COOKIE_MESSAGE_WORDS)
+
 /* As tcp_request_sock has already been extended in other places, the
  * only remaining method is to pass stack values along as function
  * parameters.  These parameters are not needed after sending SYNACK.
  */
 struct tcp_extend_values {
-	u8				cookie_bakery[TCP_COOKIE_MAX];
+	u32				cookie_bakery[COOKIE_WORKSPACE_WORDS];
 	u8				cookie_plus;
 	u8				cookie_in_always:1,
 					cookie_out_never:1;
@@ -1542,6 +1548,8 @@ static inline struct tcp_extend_values *tcp_xv(const struct request_values *rvp)
 	return (struct tcp_extend_values *)rvp;
 }
 
+extern int tcp_cookie_generator(struct tcp_extend_values *xvp);
+
 extern void tcp_v4_init(void);
 extern void tcp_init(void);
 
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 12409df..160b077 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -264,6 +264,7 @@
 #include <linux/cache.h>
 #include <linux/err.h>
 #include <linux/crypto.h>
+#include <linux/time.h>
 
 #include <net/icmp.h>
 #include <net/tcp.h>
@@ -2933,6 +2934,146 @@ EXPORT_SYMBOL(tcp_md5_hash_key);
 
 #endif
 
+/**
+ * Each Responder maintains up to two secret values concurrently for
+ * efficient secret rollover.  Each secret value has 4 states:
+ *
+ * Generating.
+ *    Generates new Responder-Cookies, but not yet used for primary
+ *    verification.  This is a short-term state, typically lasting only
+ *    one round trip time (RTT).
+ *
+ * Primary.
+ *    Used both for generation and primary verification.
+ *
+ * Retiring.
+ *    Used for verification, until the first failure that can be
+ *    verified by the newer Generating secret.  At that time, this
+ *    cookie's state is changed to Secondary, and the Generating
+ *    cookie's state is changed to Primary.  This is a short-term state,
+ *    typically lasting only one round trip time (RTT).
+ *
+ * Secondary.
+ *    Used for secondary verification, after primary verification
+ *    failures.  This state lasts no more than twice the Maximum Segment
+ *    Lifetime (2MSL).  Then, the secret is discarded.
+ */
+struct tcp_cookie_secret {
+	/* The secret is divided into two parts.  The digest part is the
+	 * equivalent of previously hashing a secret and saving the state,
+	 * and serves as an initialization vector (IV).  The message part
+	 * serves as the trailing secret.
+	 */
+	u32				secrets[COOKIE_WORKSPACE_WORDS];
+	unsigned long			expires;
+};
+
+#define TCP_SECRET_1MSL (HZ * TCP_PAWS_MSL)
+#define TCP_SECRET_2MSL (HZ * TCP_PAWS_MSL * 2)
+#define TCP_SECRET_LIFE (HZ * 600)
+
+static struct tcp_cookie_secret tcp_secret_one;
+static struct tcp_cookie_secret tcp_secret_two;
+
+static struct tcp_cookie_secret *tcp_secret_generating;
+static struct tcp_cookie_secret *tcp_secret_primary;
+static struct tcp_cookie_secret *tcp_secret_retiring;
+static struct tcp_cookie_secret *tcp_secret_secondary;
+
+static DEFINE_RWLOCK(tcp_secret_locker);
+
+/* Fill cookie_bakery with current generator, updating as needed.
+ * Returns: 0 for success.
+ */
+int tcp_cookie_generator(struct tcp_extend_values *xvp)
+{
+	u32 secrets[COOKIE_WORKSPACE_WORDS];
+	unsigned long jiffy = jiffies;
+
+	if (unlikely(NULL == tcp_secret_primary)) {
+		struct timespec tv;
+
+		getnstimeofday(&tv);
+		get_random_bytes(secrets, sizeof(secrets));
+
+		/* The first time, paranoia assumes that the randomization
+		 * function isn't as strong.  But this secret initialization
+		 * is delayed until the last possible moment (packet arrival).
+		 * Although that time is observable, it is unpredictably
+		 * variable.  Mash in the most volatile clock bits available,
+		 * and expire the secret extra quickly.
+		 */
+		secrets[COOKIE_DIGEST_WORDS+0] ^= (u32)tv.tv_nsec;
+
+		write_lock(&tcp_secret_locker);
+		if (NULL != tcp_secret_primary) {
+			/* initializated by another */
+			memcpy(&xvp->cookie_bakery[0],
+			       &tcp_secret_primary->secrets[0],
+			       sizeof(tcp_secret_primary->secrets));
+		} else {
+			/* still needs initialization */
+			memcpy(&xvp->cookie_bakery[0],
+			       &secrets[0],
+			       sizeof(secrets));
+			memcpy(&tcp_secret_one.secrets[0],
+			       &secrets[0],
+			       sizeof(secrets));
+			memcpy(&tcp_secret_two.secrets[0],
+			       &secrets[0],
+			       sizeof(secrets));
+
+			tcp_secret_one.expires = jiffy + TCP_SECRET_1MSL;
+			tcp_secret_primary = &tcp_secret_one;
+
+			tcp_secret_two.expires = 0; /* past due */
+			tcp_secret_secondary = &tcp_secret_two;
+		}
+		write_unlock(&tcp_secret_locker);
+	} else if (unlikely(time_after(jiffy, tcp_secret_primary->expires))) {
+		get_random_bytes(secrets, sizeof(secrets));
+
+		write_lock(&tcp_secret_locker);
+		if (!time_after(jiffy, tcp_secret_primary->expires)) {
+			/* refreshed by another */
+			memcpy(&xvp->cookie_bakery[0],
+			       &tcp_secret_generating->secrets[0],
+			       sizeof(tcp_secret_generating->secrets));
+		} else {
+			/* still needs refreshing */
+			memcpy(&xvp->cookie_bakery[0],
+			       &secrets[0],
+			       sizeof(secrets));
+			memcpy(&tcp_secret_secondary->secrets[0],
+			       &secrets[0],
+			       sizeof(secrets));
+
+			tcp_secret_secondary->expires = jiffy
+						      + TCP_SECRET_LIFE;
+			tcp_secret_generating = tcp_secret_secondary;
+
+			tcp_secret_primary->expires = jiffy
+						    + TCP_SECRET_2MSL;
+			tcp_secret_retiring = tcp_secret_primary;
+		}
+		write_unlock(&tcp_secret_locker);
+	} else {
+		read_lock(&tcp_secret_locker);
+		if (unlikely(NULL != tcp_secret_generating)) {
+			memcpy(&xvp->cookie_bakery[0],
+			       &tcp_secret_generating->secrets[0],
+			       sizeof(tcp_secret_generating->secrets));
+		} else {
+			memcpy(&xvp->cookie_bakery[0],
+			       &tcp_secret_primary->secrets[0],
+			       sizeof(tcp_secret_primary->secrets));
+		}
+		read_unlock(&tcp_secret_locker);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(tcp_cookie_generator);
+
 void tcp_done(struct sock *sk)
 {
 	if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
@@ -3060,6 +3201,11 @@ void __init tcp_init(void)
 	       tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size);
 
 	tcp_register_congestion_control(&tcp_reno);
+
+	tcp_secret_generating = NULL;
+	tcp_secret_primary = NULL;
+	tcp_secret_retiring = NULL;
+	tcp_secret_secondary = NULL;
 }
 
 EXPORT_SYMBOL(tcp_close);

^ permalink raw reply related

* Re: [RFC] multiqueue changes
From: Jarek Poplawski @ 2009-11-01 13:20 UTC (permalink / raw)
  To: Michael Chan
  Cc: Patrick McHardy, Eric Dumazet, David S. Miller, Linux Netdev List
In-Reply-To: <1257009952.9706.30.camel@HP1>

On Sat, Oct 31, 2009 at 10:25:52AM -0700, Michael Chan wrote:
> 
> On Fri, 2009-10-30 at 03:00 -0700, Jarek Poplawski wrote:
> > On Thu, Oct 29, 2009 at 11:12:39PM +0100, Patrick McHardy wrote:
...
> > > I currently can't see any purpose in decreasing num_tx_queues after
> > > registration instead of real_num_tx_queues.
> > 
> > I agree, but since Eric's example shows some drivers do it (almost)
> > like this, I'd prefer authors/maintainers answer this question.
> > 
> 
> We need the netdev and the private structure at the beginning of
> ->probe() to store values as we probe the device.  Later on in
> ->probe(), we'll know whether the device supports MSI-X and multiqueue.
> If we successfully enable MSI-X in ->ndo_open(), tx multiqueue will be
> used.
> 
> So if we can separate the allocation of the netdev and the private
> structure from the tx queues, we can allocate and set the exact number
> of num_tx_queues in ->ndo_open().

There is a question if we can predict in ->probe() MSI-X should be
successfully enabled in ->ndo_open() for probed hardware. If so,
then it could go e.g. like this:
->probe()
	...
	dev = alloc_etherdev_mq(sizeof(*bp), 1)
	...
	if (MSI-X_available && device_supports_MSI-X_and_multiqueue)
		realloc_netdev_mq(dev, TX_MAX_RINGS)
	register_netdev(dev)

->ndo_open()
	if (!enabled_MSI-X)
		/* something gone wrong but it's an exception */
		dev->real_num_tx_queues = 1

Otherwise, (re)allocation in ->ndo_open() would need to answer some
questions about reinitializing scheduler vs preserving qdisc stats
between opens.

Jarek P.

^ permalink raw reply

* Re: [PATCH] r8169: partial support and phy init for the 8168d
From: Ben Hutchings @ 2009-11-01 16:24 UTC (permalink / raw)
  To: Francois Romieu; +Cc: David S. Miller, netdev, Edward Hsu
In-Reply-To: <20091007224420.GA20170@electric-eye.fr.zoreil.com>

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

On Thu, 2009-10-08 at 00:44 +0200, Francois Romieu wrote:
> Extracted from Realtek's 8.012.00 r8168 driver.

There is a problem with this change:

[...]
> static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
> {
[...]
> +	static struct phy_reg phy_reg_init_2[] = {
> +		{ 0x1f, 0x0005 },
> +		{ 0x05, 0xffc2 },
> +		{ 0x1f, 0x0005 },

I interpret the following sequence of register writes as:

> +		{ 0x05, 0x8000 },
> +		{ 0x06, 0xf8f9 },
> +		{ 0x06, 0xfaef },
> +		{ 0x06, 0x59ee },
[...]

Write memory sequentially from 0x8000,

> +		{ 0x05, 0x83d4 },
> +		{ 0x06, 0x8000 },
> +		{ 0x05, 0x83d8 },
> +		{ 0x06, 0x8051 },
[...]

Change two vectors to point into what was just written. 

I believe this is patching machine code in the PHY.  And we do not have
source for that code, so it cannot possibly be distributed under GPL.

Please replace this with use of request_firmware() and submit the blob
to linux-firmware.git instead.

The same goes for phy_reg_init_1 in rtl8168d_2_hw_phy_config().

Ben.

-- 
Ben Hutchings
The generation of random numbers is too important to be left to chance.
                                                            - Robert Coveyou

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* [PATCH 1/3] sysfs directory scaling: rbtree for dirent name lookups
From: Benjamin LaHaise @ 2009-11-01 16:31 UTC (permalink / raw)
  To: Eric Dumazet, Greg Kroah-Hartman
  Cc: Eric W. Biederman, Octavian Purdila, netdev, Cosmin Ratiu,
	linux-kernel

Use an rbtree in sysfs_dirent to speed up file lookup times

Systems with large numbers (tens of thousands and more) of network 
interfaces stress the sysfs code in ways that make the linear search for 
a name match take far too long.  Avoid this by using an rbtree.

Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 5fad489..30c3fc5 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -44,6 +44,7 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd)
 {
 	struct sysfs_dirent *parent_sd = sd->s_parent;
 	struct sysfs_dirent **pos;
+	struct rb_node **new, *parent;
 
 	BUG_ON(sd->s_sibling);
 
@@ -57,6 +58,27 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd)
 	}
 	sd->s_sibling = *pos;
 	*pos = sd;
+
+	// rb tree insert
+	new = &(parent_sd->s_dir.child_rb_root.rb_node);
+	parent = NULL;
+
+	while (*new) {
+		struct sysfs_dirent *this =
+			container_of(*new, struct sysfs_dirent, s_rb_node);
+		int result = strcmp(sd->s_name, this->s_name);
+
+		parent = *new;
+		if (result < 0)
+			new = &((*new)->rb_left);
+		else if (result > 0)
+			new = &((*new)->rb_right);
+		else
+			BUG();
+	}
+
+	rb_link_node(&sd->s_rb_node, parent, new);
+	rb_insert_color(&sd->s_rb_node, &parent_sd->s_dir.child_rb_root);
 }
 
 /**
@@ -81,6 +103,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
 			break;
 		}
 	}
+
+	rb_erase(&sd->s_rb_node, &sd->s_parent->s_dir.child_rb_root);
 }
 
 /**
@@ -331,6 +355,9 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
 	sd->s_mode = mode;
 	sd->s_flags = type;
 
+	if (type == SYSFS_DIR)
+		sd->s_dir.child_rb_root = RB_ROOT;
+
 	return sd;
 
  err_out2:
@@ -630,11 +657,20 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
 struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
 				       const unsigned char *name)
 {
-	struct sysfs_dirent *sd;
-
-	for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling)
-		if (!strcmp(sd->s_name, name))
-			return sd;
+	struct rb_node *node = parent_sd->s_dir.child_rb_root.rb_node;
+
+	while (node) {
+		struct sysfs_dirent *data =
+			container_of(node, struct sysfs_dirent, s_rb_node);
+		int result;
+		result = strcmp(name, data->s_name);
+		if (result < 0)
+			node = node->rb_left;
+		else if (result > 0)
+			node = node->rb_right;
+		else
+			return data;
+	}
 	return NULL;
 }
 
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index af4c4e7..600109c 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -9,6 +9,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/rbtree.h>
 
 struct sysfs_open_dirent;
 
@@ -17,6 +18,7 @@ struct sysfs_elem_dir {
 	struct kobject		*kobj;
 	/* children list starts here and goes through sd->s_sibling */
 	struct sysfs_dirent	*children;
+	struct rb_root		child_rb_root;
 };
 
 struct sysfs_elem_symlink {
@@ -52,6 +54,7 @@ struct sysfs_dirent {
 	atomic_t		s_active;
 	struct sysfs_dirent	*s_parent;
 	struct sysfs_dirent	*s_sibling;
+	struct rb_node		s_rb_node;
 	const char		*s_name;
 
 	union {

^ permalink raw reply related

* [PATCH 2/3] sysfs directory scaling: doubly linked list for dirents
From: Benjamin LaHaise @ 2009-11-01 16:32 UTC (permalink / raw)
  To: Eric Dumazet, Greg Kroah-Hartman
  Cc: Eric W. Biederman, Octavian Purdila, netdev, Cosmin Ratiu,
	linux-kernel
In-Reply-To: <20091101163130.GA7911@kvack.org>

When adding/removing large numbers of entries from sysfs directories, one 
hot spot is in the link and unlink operations of sysfs.  When linking a 
new sysfs_dirent into the tree, operation can be significantly sped up by 
starting at the end of the list rather than the beginning.  Unlink is 
improved by using a doubly linked list.

Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
diff -u b/fs/sysfs/dir.c b/fs/sysfs/dir.c
--- b/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -43,11 +43,18 @@
 static void sysfs_link_sibling(struct sysfs_dirent *sd)
 {
 	struct sysfs_dirent *parent_sd = sd->s_parent;
-	struct sysfs_dirent **pos;
+	struct sysfs_dirent **pos, *prev = NULL;
 	struct rb_node **new, *parent;
 
 	BUG_ON(sd->s_sibling);
 
+	if (parent_sd->s_dir.children_tail &&
+	    parent_sd->s_dir.children_tail->s_ino < sd->s_ino) {
+		prev = parent_sd->s_dir.children_tail;
+		pos = &prev->s_sibling;
+		goto got_it;
+	}
+
 	/* Store directory entries in order by ino.  This allows
 	 * readdir to properly restart without having to add a
 	 * cursor into the s_dir.children list.
@@ -55,8 +62,13 @@
 	for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) {
 		if (sd->s_ino < (*pos)->s_ino)
 			break;
+		prev = *pos;
 	}
+got_it:
+	if (prev == parent_sd->s_dir.children_tail)
+		parent_sd->s_dir.children_tail = sd;
 	sd->s_sibling = *pos;
+	sd->s_sibling_prev = prev;
 	*pos = sd;
 
 	// rb tree insert
@@ -93,17 +105,20 @@
  */
 static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
 {
-	struct sysfs_dirent **pos;
-
-	for (pos = &sd->s_parent->s_dir.children; *pos;
-	     pos = &(*pos)->s_sibling) {
-		if (*pos == sd) {
-			*pos = sd->s_sibling;
-			sd->s_sibling = NULL;
-			break;
-		}
-	}
+	struct sysfs_dirent **pos, *prev = NULL;
 
+	prev = sd->s_sibling_prev;
+	if (prev)
+		pos = &prev->s_sibling;
+	else
+		pos = &sd->s_parent->s_dir.children;
+	if (sd == sd->s_parent->s_dir.children_tail)
+		sd->s_parent->s_dir.children_tail = prev;
+	*pos = sd->s_sibling;
+	if (sd->s_sibling)
+		sd->s_sibling->s_sibling_prev = prev;
+	
+	sd->s_sibling_prev = NULL;
 	rb_erase(&sd->s_rb_node, &sd->s_parent->s_dir.child_rb_root);
 }
 
diff -u b/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
--- b/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -17,7 +17,9 @@
 struct sysfs_elem_dir {
 	struct kobject		*kobj;
 	/* children list starts here and goes through sd->s_sibling */
+	
 	struct sysfs_dirent	*children;
+	struct sysfs_dirent	*children_tail;
 	struct rb_root		child_rb_root;
 };
 
@@ -54,6 +56,7 @@
 	atomic_t		s_active;
 	struct sysfs_dirent	*s_parent;
 	struct sysfs_dirent	*s_sibling;
+	struct sysfs_dirent	*s_sibling_prev;
 	struct rb_node		s_rb_node;
 	const char		*s_name;
 

^ permalink raw reply

* [PATCH 2/3] sysfs directory scaling: count number of children dirs
From: Benjamin LaHaise @ 2009-11-01 16:33 UTC (permalink / raw)
  To: Eric Dumazet, Greg Kroah-Hartman
  Cc: Eric W. Biederman, Octavian Purdila, netdev, Cosmin Ratiu,
	linux-kernel
In-Reply-To: <20091101163230.GB7911@kvack.org>

sysfs_count_nlink() is a bottleneck during mass bring up of network 
interfaces.  Eliminate this problem by tracking the number of directories.

Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
diff -u b/fs/sysfs/dir.c b/fs/sysfs/dir.c
--- b/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -70,6 +70,7 @@
 	sd->s_sibling = *pos;
 	sd->s_sibling_prev = prev;
 	*pos = sd;
+	parent_sd->s_nr_children_dir += (sysfs_type(sd) == SYSFS_DIR);
 
 	// rb tree insert
 	new = &(parent_sd->s_dir.child_rb_root.rb_node);
@@ -118,6 +119,7 @@
 	if (sd->s_sibling)
 		sd->s_sibling->s_sibling_prev = prev;
 	
+	sd->s_parent->s_nr_children_dir -= (sysfs_type(sd) == SYSFS_DIR);
 	sd->s_sibling_prev = NULL;
 	rb_erase(&sd->s_rb_node, &sd->s_parent->s_dir.child_rb_root);
 }
diff -u b/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
--- b/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -71,6 +71,8 @@
 	ino_t			s_ino;
 	umode_t			s_mode;
 	struct sysfs_inode_attrs *s_iattr;
+
+	int			s_nr_children_dir;
 };
 
 #define SD_DEACTIVATED_BIAS		INT_MIN
only in patch2:
unchanged:
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -191,14 +191,7 @@ static struct lock_class_key sysfs_inode_imutex_key;
 
 static int sysfs_count_nlink(struct sysfs_dirent *sd)
 {
-	struct sysfs_dirent *child;
-	int nr = 0;
-
-	for (child = sd->s_dir.children; child; child = child->s_sibling)
-		if (sysfs_type(child) == SYSFS_DIR)
-			nr++;
-
-	return nr + 2;
+	return sd->s_nr_children_dir + 2;
 }
 
 static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)

^ permalink raw reply

* Re: [PATCH net-next-2.6] Driver for the Microchip MCP251x SPI CAN controllers
From: Paul Thomas @ 2009-11-01 16:40 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	Christian Pellegrin, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <4AED5589.3090106-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

Yes, I will be testing ready to work on this hopefully on Monday or
Tuesday. Is this the correct git tree to patch against?
http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=summary

Should I just pull the latest?

thanks,
Paul

^ permalink raw reply

* Re: [PATCH net-next-2.6] Driver for the Microchip MCP251x SPI CAN controllers
From: Wolfgang Grandegger @ 2009-11-01 16:44 UTC (permalink / raw)
  To: Paul Thomas
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	Christian Pellegrin, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <c785bba30911010840m2ad73abawf8434f42337a26d3-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Paul Thomas wrote:
> Yes, I will be testing ready to work on this hopefully on Monday or
> Tuesday. Is this the correct git tree to patch against?
> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=summary

Yes:

git clone \
    git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6

> Should I just pull the latest?

Yes.

Wolfgang.

^ 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