Imported xen patches.
authorBen Schweikert <trikolon@ipfire.org>
Thu, 16 Apr 2009 15:42:00 +0000 (15:42 +0000)
committerBen Schweikert <trikolon@ipfire.org>
Thu, 16 Apr 2009 15:47:34 +0000 (15:47 +0000)
73 files changed:
src/patches/60000_add-console-use-vt.patch1 [new file with mode: 0644]
src/patches/60001_linux-2.6.19-rc1-kexec-move_segment_code-i386.patch1 [new file with mode: 0644]
src/patches/60002_linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch1 [new file with mode: 0644]
src/patches/60003_ipv6-no-autoconf.patch1 [new file with mode: 0644]
src/patches/60004_pci-reassign-resources.patch1 [new file with mode: 0644]
src/patches/60005_sfc-driverlink.patch1 [new file with mode: 0644]
src/patches/60006_sfc-resource-driver.patch1 [new file with mode: 0644]
src/patches/60007_sfc-driverlink-conditional.patch1 [new file with mode: 0644]
src/patches/60008_xen3-auto-xen-arch.patch1 [new file with mode: 0644]
src/patches/60009_xen3-auto-xen-drivers.patch1 [new file with mode: 0644]
src/patches/60010_xen3-auto-include-xen-interface.patch1 [new file with mode: 0644]
src/patches/60011_xen3-auto-xen-kconfig.patch1 [new file with mode: 0644]
src/patches/60012_xen3-auto-common.patch1 [new file with mode: 0644]
src/patches/60013_xen3-auto-arch-x86.patch1 [new file with mode: 0644]
src/patches/60014_xen3-auto-arch-i386.patch1 [new file with mode: 0644]
src/patches/60015_xen3-auto-arch-x86_64.patch1 [new file with mode: 0644]
src/patches/60016_xen3-fixup-xen.patch1 [new file with mode: 0644]
src/patches/60017_735-balloon-exit.patch1 [new file with mode: 0644]
src/patches/60018_737-kexec-free.patch1 [new file with mode: 0644]
src/patches/60019_740-blkback-resource-leak.patch1 [new file with mode: 0644]
src/patches/60020_746-pirq-status-page.patch1 [new file with mode: 0644]
src/patches/60021_747-x86-undo-mfn-limit.patch1 [new file with mode: 0644]
src/patches/60022_748-x86-ioapic-cleanup.patch1 [new file with mode: 0644]
src/patches/60023_xen3-fixup-kconfig.patch1 [new file with mode: 0644]
src/patches/60024_xen3-fixup-common.patch1 [new file with mode: 0644]
src/patches/60025_xen3-fixup-arch-x86.patch1 [new file with mode: 0644]
src/patches/60026_xen3-fixup-sfc.patch1 [new file with mode: 0644]
src/patches/60027_xen3-patch-2.6.18.patch1 [new file with mode: 0644]
src/patches/60028_xen3-patch-2.6.19.patch1 [new file with mode: 0644]
src/patches/60029_xen3-patch-2.6.20.patch1 [new file with mode: 0644]
src/patches/60030_xen3-patch-2.6.21.patch1 [new file with mode: 0644]
src/patches/60031_xen3-patch-2.6.22.patch1 [new file with mode: 0644]
src/patches/60032_xen3-patch-2.6.23.patch1 [new file with mode: 0644]
src/patches/60033_xen3-patch-2.6.24.patch1 [new file with mode: 0644]
src/patches/60034_xen3-patch-2.6.25.patch1 [new file with mode: 0644]
src/patches/60035_xen3-patch-2.6.26.patch1 [new file with mode: 0644]
src/patches/60036_xen3-patch-2.6.27.patch1 [new file with mode: 0644]
src/patches/60037_xen3-patch-2.6.27.1-2.patch1 [new file with mode: 0644]
src/patches/60038_xen3-patch-2.6.27.3-4.patch1 [new file with mode: 0644]
src/patches/60039_xen3-patch-2.6.27.4-5.patch1 [new file with mode: 0644]
src/patches/60040_xen3-patch-2.6.27.5-6.patch1 [new file with mode: 0644]
src/patches/60041_xen3-panic-on-io-nmi.patch1 [new file with mode: 0644]
src/patches/60042_xen-balloon-max-target.patch1 [new file with mode: 0644]
src/patches/60043_xen-blkback-cdrom.patch1 [new file with mode: 0644]
src/patches/60044_xen-blktap-write-barriers.patch1 [new file with mode: 0644]
src/patches/60045_xen-scsifront-block-timeout-update.patch1 [new file with mode: 0644]
src/patches/60046_xen-op-packet.patch1 [new file with mode: 0644]
src/patches/60047_xen-blkfront-cdrom.patch1 [new file with mode: 0644]
src/patches/60048_xen-sections.patch1 [new file with mode: 0644]
src/patches/60049_xen-kconfig-compat-3.2.0.patch1 [new file with mode: 0644]
src/patches/60050_xen-cpufreq-report.patch1 [new file with mode: 0644]
src/patches/60051_xen-rt2860-build.patch1 [new file with mode: 0644]
src/patches/60052_xen-sysdev-suspend.patch1 [new file with mode: 0644]
src/patches/60053_xen-ipi-per-cpu-irq.patch1 [new file with mode: 0644]
src/patches/60054_xen-virq-per-cpu-irq.patch1 [new file with mode: 0644]
src/patches/60055_xen-configurable-guest-devices.patch1 [new file with mode: 0644]
src/patches/60056_xen-netback-nr-irqs.patch1 [new file with mode: 0644]
src/patches/60057_xen-netback-notify-multi.patch1 [new file with mode: 0644]
src/patches/60058_xen-x86-panic-no-reboot.patch1 [new file with mode: 0644]
src/patches/60059_xen-x86-dcr-fallback.patch1 [new file with mode: 0644]
src/patches/60060_xen-x86-consistent-nmi.patch1 [new file with mode: 0644]
src/patches/60061_xen-x86-no-lapic.patch1 [new file with mode: 0644]
src/patches/60062_xen-x86-pmd-handling.patch1 [new file with mode: 0644]
src/patches/60063_xen-x86-bigmem.patch1 [new file with mode: 0644]
src/patches/60064_xen-x86-machphys-prediction.patch1 [new file with mode: 0644]
src/patches/60065_xen-x86-no-lazy-tlb.patch1 [new file with mode: 0644]
src/patches/60066_xen-x86-exit-mmap.patch1 [new file with mode: 0644]
src/patches/60067_xen-i386-panic-on-oops.patch1 [new file with mode: 0644]
src/patches/60068_xen-x86_64-pgd-pin.patch1 [new file with mode: 0644]
src/patches/60069_xen-x86_64-pgd-alloc-order.patch1 [new file with mode: 0644]
src/patches/60070_xen-x86_64-dump-user-pgt.patch1 [new file with mode: 0644]
src/patches/xen_aio.diff [new file with mode: 0644]
src/patches/xen_skbuff.diff [new file with mode: 0644]

diff --git a/src/patches/60000_add-console-use-vt.patch1 b/src/patches/60000_add-console-use-vt.patch1
new file mode 100644 (file)
index 0000000..2fa3e91
--- /dev/null
@@ -0,0 +1,58 @@
+Subject: add console_use_vt
+From: kraxel@suse.de
+Patch-mainline: no
+
+$subject says all
+
+---
+ drivers/char/tty_io.c   |    7 ++++++-
+ include/linux/console.h |    1 +
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -136,6 +136,8 @@ LIST_HEAD(tty_drivers);                    /* linked list
+ DEFINE_MUTEX(tty_mutex);
+ EXPORT_SYMBOL(tty_mutex);
++int console_use_vt = 1;
++
+ #ifdef CONFIG_UNIX98_PTYS
+ extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
+ static int ptmx_open(struct inode *, struct file *);
+@@ -2200,7 +2202,7 @@ retry_open:
+               goto got_driver;
+       }
+ #ifdef CONFIG_VT
+-      if (device == MKDEV(TTY_MAJOR, 0)) {
++      if (console_use_vt && device == MKDEV(TTY_MAJOR, 0)) {
+               extern struct tty_driver *console_driver;
+               driver = console_driver;
+               index = fg_console;
+@@ -3729,6 +3731,8 @@ static int __init tty_init(void)
+ #endif
+ #ifdef CONFIG_VT
++      if (!console_use_vt)
++              goto out_vt;
+       cdev_init(&vc0_cdev, &console_fops);
+       if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
+           register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
+@@ -3736,6 +3740,7 @@ static int __init tty_init(void)
+       device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+       vty_init();
++ out_vt:
+ #endif
+       return 0;
+ }
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -63,6 +63,7 @@ extern const struct consw dummy_con; /* 
+ extern const struct consw vga_con;    /* VGA text console */
+ extern const struct consw newport_con;        /* SGI Newport console  */
+ extern const struct consw prom_con;   /* SPARC PROM console */
++extern int console_use_vt;
+ int con_is_bound(const struct consw *csw);
+ int register_con_driver(const struct consw *csw, int first, int last);
diff --git a/src/patches/60001_linux-2.6.19-rc1-kexec-move_segment_code-i386.patch1 b/src/patches/60001_linux-2.6.19-rc1-kexec-move_segment_code-i386.patch1
new file mode 100644 (file)
index 0000000..1439e03
--- /dev/null
@@ -0,0 +1,178 @@
+Subject: kexec: Move asm segment handling code to the assembly file (i386)
+From: http://xenbits.xensource.com/xen-unstable.hg (tip 13816)
+Patch-mainline: obsolete
+
+This patch moves the idt, gdt, and segment handling code from machine_kexec.c
+to relocate_kernel.S. The main reason behind this move is to avoid code 
+duplication in the Xen hypervisor. With this patch all code required to kexec
+is put on the control page.
+
+On top of that this patch also counts as a cleanup - I think it is much
+nicer to write assembly directly in assembly files than wrap inline assembly
+in C functions for no apparent reason.
+
+Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
+Acked-by: jbeulich@novell.com
+---
+
+ Applies to 2.6.19-rc1.
+
+ machine_kexec.c   |   59 -----------------------------------------------------
+ relocate_kernel.S |   58 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 53 insertions(+), 64 deletions(-)
+
+Index: head-2008-11-17/arch/x86/kernel/machine_kexec_32.c
+===================================================================
+--- head-2008-11-17.orig/arch/x86/kernel/machine_kexec_32.c    2008-11-17 13:15:56.000000000 +0100
++++ head-2008-11-17/arch/x86/kernel/machine_kexec_32.c 2008-11-17 13:38:03.000000000 +0100
+@@ -34,48 +34,6 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED
+ static u32 kexec_pte0[1024] PAGE_ALIGNED;
+ static u32 kexec_pte1[1024] PAGE_ALIGNED;
+-static void set_idt(void *newidt, __u16 limit)
+-{
+-      struct desc_ptr curidt;
+-
+-      /* ia32 supports unaliged loads & stores */
+-      curidt.size    = limit;
+-      curidt.address = (unsigned long)newidt;
+-
+-      load_idt(&curidt);
+-}
+-
+-
+-static void set_gdt(void *newgdt, __u16 limit)
+-{
+-      struct desc_ptr curgdt;
+-
+-      /* ia32 supports unaligned loads & stores */
+-      curgdt.size    = limit;
+-      curgdt.address = (unsigned long)newgdt;
+-
+-      load_gdt(&curgdt);
+-}
+-
+-static void load_segments(void)
+-{
+-#define __STR(X) #X
+-#define STR(X) __STR(X)
+-
+-      __asm__ __volatile__ (
+-              "\tljmp $"STR(__KERNEL_CS)",$1f\n"
+-              "\t1:\n"
+-              "\tmovl $"STR(__KERNEL_DS)",%%eax\n"
+-              "\tmovl %%eax,%%ds\n"
+-              "\tmovl %%eax,%%es\n"
+-              "\tmovl %%eax,%%fs\n"
+-              "\tmovl %%eax,%%gs\n"
+-              "\tmovl %%eax,%%ss\n"
+-              ::: "eax", "memory");
+-#undef STR
+-#undef __STR
+-}
+-
+ /*
+  * A architecture hook called to validate the
+  * proposed image and prepare the control pages
+@@ -167,23 +125,6 @@ void machine_kexec(struct kimage *image)
+               page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
+                                               << PAGE_SHIFT);
+-      /* The segment registers are funny things, they have both a
+-       * visible and an invisible part.  Whenever the visible part is
+-       * set to a specific selector, the invisible part is loaded
+-       * with from a table in memory.  At no other time is the
+-       * descriptor table in memory accessed.
+-       *
+-       * I take advantage of this here by force loading the
+-       * segments, before I zap the gdt with an invalid value.
+-       */
+-      load_segments();
+-      /* The gdt & idt are now invalid.
+-       * If you want to load them you must set up your own idt & gdt.
+-       */
+-      set_gdt(phys_to_virt(0),0);
+-      set_idt(phys_to_virt(0),0);
+-
+-      /* now call it */
+       image->start = relocate_kernel_ptr((unsigned long)image->head,
+                                          (unsigned long)page_list,
+                                          image->start, cpu_has_pae,
+Index: head-2008-11-17/arch/x86/kernel/relocate_kernel_32.S
+===================================================================
+--- head-2008-11-17.orig/arch/x86/kernel/relocate_kernel_32.S  2008-11-17 13:15:56.000000000 +0100
++++ head-2008-11-17/arch/x86/kernel/relocate_kernel_32.S       2008-11-17 13:38:03.000000000 +0100
+@@ -199,14 +199,45 @@ relocate_new_kernel:
+       movl    PTR(PA_PGD)(%ebp), %eax
+       movl    %eax, %cr3
++      /* setup idt */
++      movl    %edi, %eax
++      addl    $(idt_48 - relocate_kernel), %eax
++      lidtl   (%eax)
++
++      /* setup gdt */
++      movl    %edi, %eax
++      addl    $(gdt - relocate_kernel), %eax
++      movl    %edi, %esi
++      addl    $((gdt_48 - relocate_kernel) + 2), %esi
++      movl    %eax, (%esi)
++
++      movl    %edi, %eax
++      addl    $(gdt_48 - relocate_kernel), %eax
++      lgdtl   (%eax)
++
++      /* setup data segment registers */
++      mov     $(gdt_ds - gdt), %eax
++      mov     %eax, %ds
++      mov     %eax, %es
++      mov     %eax, %fs
++      mov     %eax, %gs
++      mov     %eax, %ss
++
+       /* setup a new stack at the end of the physical control page */
+       lea     PAGE_SIZE(%edi), %esp
+-      /* jump to identity mapped page */
+-      movl    %edi, %eax
+-      addl    $(identity_mapped - relocate_kernel), %eax
+-      pushl   %eax
+-      ret
++      /* load new code segment and jump to identity mapped page */
++      movl    %edi, %esi
++      xorl    %eax, %eax
++      pushl   %eax
++      pushl   %esi
++      pushl   %eax
++      movl    $(gdt_cs - gdt), %eax
++      pushl   %eax
++      movl    %edi, %eax
++      addl    $(identity_mapped - relocate_kernel),%eax
++      pushl   %eax
++      iretl
+ identity_mapped:
+       /* store the start address on the stack */
+@@ -378,5 +409,22 @@ swap_pages:
+       popl    %ebp
+       ret
++      .align  16
++gdt:
++      .quad   0x0000000000000000      /* NULL descriptor */
++gdt_cs:
++      .quad   0x00cf9a000000ffff      /* kernel 4GB code at 0x00000000 */
++gdt_ds:
++      .quad   0x00cf92000000ffff      /* kernel 4GB data at 0x00000000 */
++gdt_end:
++
++gdt_48:
++      .word   gdt_end - gdt - 1       /* limit */
++      .long   0                       /* base - filled in by code above */
++
++idt_48:
++      .word   0                       /* limit */
++      .long   0                       /* base */
++
+       .globl kexec_control_code_size
+ .set kexec_control_code_size, . - relocate_kernel
diff --git a/src/patches/60002_linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch1 b/src/patches/60002_linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch1
new file mode 100644 (file)
index 0000000..5235a03
--- /dev/null
@@ -0,0 +1,168 @@
+Subject: kexec: Move asm segment handling code to the assembly file (x86_64)
+From: http://xenbits.xensource.com/xen-unstable.hg (tip 13816)
+Patch-mainline: obsolete
+
+This patch moves the idt, gdt, and segment handling code from machine_kexec.c
+to relocate_kernel.S.  The main reason behind this move is to avoid code 
+duplication in the Xen hypervisor. With this patch all code required to kexec
+is put on the control page.
+
+On top of that this patch also counts as a cleanup - I think it is much
+nicer to write assembly directly in assembly files than wrap inline assembly
+in C functions for no apparent reason.
+
+Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
+Acked-by: jbeulich@novell.com
+---
+
+ Applies to 2.6.19-rc1.
+
+ machine_kexec.c   |   58 -----------------------------------------------------
+ relocate_kernel.S |   50 +++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 45 insertions(+), 63 deletions(-)
+
+Index: head-2008-08-18/arch/x86/kernel/machine_kexec_64.c
+===================================================================
+--- head-2008-08-18.orig/arch/x86/kernel/machine_kexec_64.c    2008-08-18 09:05:04.000000000 +0200
++++ head-2008-08-18/arch/x86/kernel/machine_kexec_64.c 2008-08-18 10:13:08.000000000 +0200
+@@ -115,47 +115,6 @@ static int init_pgtable(struct kimage *i
+       return init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
+ }
+-static void set_idt(void *newidt, u16 limit)
+-{
+-      struct desc_ptr curidt;
+-
+-      /* x86-64 supports unaliged loads & stores */
+-      curidt.size    = limit;
+-      curidt.address = (unsigned long)newidt;
+-
+-      __asm__ __volatile__ (
+-              "lidtq %0\n"
+-              : : "m" (curidt)
+-              );
+-};
+-
+-
+-static void set_gdt(void *newgdt, u16 limit)
+-{
+-      struct desc_ptr curgdt;
+-
+-      /* x86-64 supports unaligned loads & stores */
+-      curgdt.size    = limit;
+-      curgdt.address = (unsigned long)newgdt;
+-
+-      __asm__ __volatile__ (
+-              "lgdtq %0\n"
+-              : : "m" (curgdt)
+-              );
+-};
+-
+-static void load_segments(void)
+-{
+-      __asm__ __volatile__ (
+-              "\tmovl %0,%%ds\n"
+-              "\tmovl %0,%%es\n"
+-              "\tmovl %0,%%ss\n"
+-              "\tmovl %0,%%fs\n"
+-              "\tmovl %0,%%gs\n"
+-              : : "a" (__KERNEL_DS) : "memory"
+-              );
+-}
+-
+ int machine_kexec_prepare(struct kimage *image)
+ {
+       unsigned long start_pgtable;
+@@ -214,23 +173,6 @@ void machine_kexec(struct kimage *image)
+       page_list[PA_TABLE_PAGE] =
+         (unsigned long)__pa(page_address(image->control_code_page));
+-      /* The segment registers are funny things, they have both a
+-       * visible and an invisible part.  Whenever the visible part is
+-       * set to a specific selector, the invisible part is loaded
+-       * with from a table in memory.  At no other time is the
+-       * descriptor table in memory accessed.
+-       *
+-       * I take advantage of this here by force loading the
+-       * segments, before I zap the gdt with an invalid value.
+-       */
+-      load_segments();
+-      /* The gdt & idt are now invalid.
+-       * If you want to load them you must set up your own idt & gdt.
+-       */
+-      set_gdt(phys_to_virt(0),0);
+-      set_idt(phys_to_virt(0),0);
+-
+-      /* now call it */
+       relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
+                       image->start);
+ }
+Index: head-2008-08-18/arch/x86/kernel/relocate_kernel_64.S
+===================================================================
+--- head-2008-08-18.orig/arch/x86/kernel/relocate_kernel_64.S  2008-07-13 23:51:29.000000000 +0200
++++ head-2008-08-18/arch/x86/kernel/relocate_kernel_64.S       2008-08-18 10:13:08.000000000 +0200
+@@ -160,13 +160,39 @@ relocate_new_kernel:
+       movq    PTR(PA_PGD)(%rsi), %r9
+       movq    %r9, %cr3
++      /* setup idt */
++      movq    %r8, %rax
++      addq    $(idt_80 - relocate_kernel), %rax
++      lidtq   (%rax)
++
++      /* setup gdt */
++      movq    %r8, %rax
++      addq    $(gdt - relocate_kernel), %rax
++      movq    %r8, %r9
++      addq    $((gdt_80 - relocate_kernel) + 2), %r9
++      movq    %rax, (%r9)
++
++      movq    %r8, %rax
++      addq    $(gdt_80 - relocate_kernel), %rax
++      lgdtq   (%rax)
++
++      /* setup data segment registers */
++      xorl    %eax, %eax
++      movl    %eax, %ds
++      movl    %eax, %es
++      movl    %eax, %fs
++      movl    %eax, %gs
++      movl    %eax, %ss
++
+       /* setup a new stack at the end of the physical control page */
+       lea     PAGE_SIZE(%r8), %rsp
+-      /* jump to identity mapped page */
+-      addq    $(identity_mapped - relocate_kernel), %r8
+-      pushq   %r8
+-      ret
++      /* load new code segment and jump to identity mapped page */
++      movq    %r8, %rax
++      addq    $(identity_mapped - relocate_kernel), %rax
++      pushq   $(gdt_cs - gdt)
++      pushq   %rax
++      lretq
+ identity_mapped:
+       /* store the start address on the stack */
+@@ -262,5 +288,19 @@ identity_mapped:
+       xorq    %r13, %r13
+       xorq    %r14, %r14
+       xorq    %r15, %r15
+-
+       ret
++
++      .align  16
++gdt:
++      .quad   0x0000000000000000      /* NULL descriptor */
++gdt_cs:
++      .quad   0x00af9a000000ffff
++gdt_end:
++
++gdt_80:
++      .word   gdt_end - gdt - 1       /* limit */
++      .quad   0                       /* base - filled in by code above */
++
++idt_80:
++      .word   0                       /* limit */
++      .quad   0                       /* base */
diff --git a/src/patches/60003_ipv6-no-autoconf.patch1 b/src/patches/60003_ipv6-no-autoconf.patch1
new file mode 100644 (file)
index 0000000..10ff1df
--- /dev/null
@@ -0,0 +1,39 @@
+From: Olaf Kirch <okir@suse.de>
+Subject: Allow to bring up network interface w/o ipv6 autoconf
+References: 161888
+
+When bringing up a xen bridge device, it will always be configured to
+use a MAC address of ff:ff:ff:ff:ff:fe.  This greatly confuses IPv6 DAD,
+which starts logging lots and lots of useless messages to syslog.
+
+We really want to disable IPv6 on these interfaces, and there doesn't
+seem to be a reliable way to do this without bringing the interface
+up first (and triggering IPv6 autoconf). 
+
+This patch makes autoconf (DAD and router discovery) depend on the
+interface's ability to do multicast. Turning off multicast for an
+interface before bringing it up will suppress autoconfiguration.
+
+ net/ipv6/addrconf.c |    2 ++
+ 1 files changed, 2 insertions(+)
+
+Index: head-2008-09-25/net/ipv6/addrconf.c
+===================================================================
+--- head-2008-09-25.orig/net/ipv6/addrconf.c   2008-09-25 13:56:12.000000000 +0200
++++ head-2008-09-25/net/ipv6/addrconf.c        2008-09-25 14:15:19.000000000 +0200
+@@ -2781,6 +2781,7 @@ static void addrconf_dad_start(struct in
+       spin_lock_bh(&ifp->lock);
+       if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
++          !(dev->flags&IFF_MULTICAST) ||
+           idev->cnf.accept_dad < 1 ||
+           !(ifp->flags&IFA_F_TENTATIVE) ||
+           ifp->flags & IFA_F_NODAD) {
+@@ -2878,6 +2879,7 @@ static void addrconf_dad_completed(struc
+       if (ifp->idev->cnf.forwarding == 0 &&
+           ifp->idev->cnf.rtr_solicits > 0 &&
+           (dev->flags&IFF_LOOPBACK) == 0 &&
++          (dev->flags & IFF_MULTICAST) &&
+           (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
+               /*
+                *      If a host as already performed a random delay
diff --git a/src/patches/60004_pci-reassign-resources.patch1 b/src/patches/60004_pci-reassign-resources.patch1
new file mode 100644 (file)
index 0000000..2d25ca8
--- /dev/null
@@ -0,0 +1,307 @@
+Subject: xen/dom0: Reassign memory resources to device for pci passthrough
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 745:2268be46c75e)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+Index: head-2008-12-01/drivers/pci/Makefile
+===================================================================
+--- head-2008-12-01.orig/drivers/pci/Makefile  2008-12-01 10:53:15.000000000 +0100
++++ head-2008-12-01/drivers/pci/Makefile       2008-10-21 13:09:46.000000000 +0200
+@@ -4,6 +4,7 @@
+ obj-y         += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
+                       pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
++obj-$(CONFIG_PCI_REASSIGN) += reassigndev.o
+ obj-$(CONFIG_PROC_FS) += proc.o
+ # Build PCI Express stuff if needed
+Index: head-2008-12-01/drivers/pci/pci.h
+===================================================================
+--- head-2008-12-01.orig/drivers/pci/pci.h     2008-12-01 10:53:15.000000000 +0100
++++ head-2008-12-01/drivers/pci/pci.h  2008-10-21 13:09:01.000000000 +0200
+@@ -144,3 +144,9 @@ struct pci_slot_attribute {
+ };
+ #define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
++#ifdef CONFIG_PCI_REASSIGN
++extern int is_reassigndev(struct pci_dev *dev);
++extern void pci_disable_bridge_window(struct pci_dev *dev);
++#else
++#define is_reassigndev(dev) 0
++#endif
+Index: head-2008-12-01/drivers/pci/quirks.c
+===================================================================
+--- head-2008-12-01.orig/drivers/pci/quirks.c  2008-12-01 10:53:15.000000000 +0100
++++ head-2008-12-01/drivers/pci/quirks.c       2008-10-29 10:52:40.000000000 +0100
+@@ -24,6 +24,54 @@
+ #include <linux/kallsyms.h>
+ #include "pci.h"
++#ifdef CONFIG_PCI_REASSIGN
++/*
++ * This quirk function disables the device and releases resources
++ * which is specified by kernel's boot parameter 'reassigndev'.
++ * Later on, kernel will assign page-aligned memory resource back
++ * to that device.
++ */
++static void __devinit quirk_release_resources(struct pci_dev *dev)
++{
++      int i;
++      struct resource *r;
++
++      if (is_reassigndev(dev)) {
++              if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
++                  (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
++                      /* PCI Host Bridge isn't a target device */
++                      return;
++              }
++              printk(KERN_INFO
++                      "PCI: Disable device and release resources [%s].\n",
++                      pci_name(dev));
++              pci_disable_device(dev);
++
++              for (i=0; i < PCI_NUM_RESOURCES; i++) {
++                      r = &dev->resource[i];
++                      if (!(r->flags & IORESOURCE_MEM))
++                              continue;
++
++                      r->end = r->end - r->start;
++                      r->start = 0;
++
++                      if (i < PCI_BRIDGE_RESOURCES) {
++                              pci_update_resource(dev, r, i);
++                      }
++              }
++              /* need to disable bridge's resource window,
++               * to make kernel enable to reassign new resource
++               * window later on.
++               */
++              if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
++                  (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
++                      pci_disable_bridge_window(dev);
++              }
++      }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_release_resources);
++#endif
++
+ /* The Mellanox Tavor device gives false positive parity errors
+  * Mark this device with a broken_parity_status, to allow
+  * PCI scanning code to "skip" this now blacklisted device.
+Index: head-2008-12-01/drivers/pci/reassigndev.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-12-01/drivers/pci/reassigndev.c  2008-10-21 13:13:38.000000000 +0200
+@@ -0,0 +1,80 @@
++/*
++ * Copyright (c) 2008, NEC Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include "pci.h"
++
++
++#define       REASSIGNDEV_PARAM_MAX   (2048)
++#define       TOKEN_MAX       (12)    /* "SSSS:BB:DD.F" length is 12 */
++
++static char param_reassigndev[REASSIGNDEV_PARAM_MAX] = {0};
++
++static int __init reassigndev_setup(char *str)
++{
++      strncpy(param_reassigndev, str, REASSIGNDEV_PARAM_MAX);
++      param_reassigndev[REASSIGNDEV_PARAM_MAX - 1] = '\0';
++      return 1;
++}
++__setup("reassigndev=", reassigndev_setup);
++
++int is_reassigndev(struct pci_dev *dev)
++{
++      char dev_str[TOKEN_MAX+1];
++      int seg, bus, slot, func;
++      int len;
++      char *p, *next_str;
++
++      p = param_reassigndev;
++      for (; p; p = next_str + 1) {
++              next_str = strpbrk(p, ",");
++              if (next_str) {
++                      len = next_str - p;
++              } else {
++                      len = strlen(p);
++              }
++              if (len > 0 && len <= TOKEN_MAX) {
++                      strncpy(dev_str, p, len);
++                      *(dev_str + len) = '\0';
++
++                      if (sscanf(dev_str, "%x:%x:%x.%x",
++                              &seg, &bus, &slot, &func) != 4) {
++                              if (sscanf(dev_str, "%x:%x.%x",
++                                      &bus, &slot, &func) == 3) {
++                                      seg = 0;
++                              } else {
++                                      /* failed to scan strings */
++                                      seg = -1;
++                                      bus = -1;
++                              }
++                      }
++                      if (seg == pci_domain_nr(dev->bus) &&
++                          bus == dev->bus->number &&
++                          slot == PCI_SLOT(dev->devfn) &&
++                          func == PCI_FUNC(dev->devfn)) {
++                              /* It's a target device */
++                              return 1;
++                      }
++              }
++              if (!next_str)
++                      break;
++      }
++
++      return 0;
++}
+Index: head-2008-12-01/drivers/pci/setup-bus.c
+===================================================================
+--- head-2008-12-01.orig/drivers/pci/setup-bus.c       2008-12-01 10:53:15.000000000 +0100
++++ head-2008-12-01/drivers/pci/setup-bus.c    2008-10-21 13:09:01.000000000 +0200
+@@ -26,6 +26,7 @@
+ #include <linux/cache.h>
+ #include <linux/slab.h>
++#include "pci.h"
+ static void pbus_assign_resources_sorted(struct pci_bus *bus)
+ {
+@@ -343,7 +344,8 @@ static int pbus_size_mem(struct pci_bus 
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               int i;
+-              
++              int reassign = is_reassigndev(dev);
++
+               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                       struct resource *r = &dev->resource[i];
+                       resource_size_t r_size;
+@@ -351,6 +353,10 @@ static int pbus_size_mem(struct pci_bus 
+                       if (r->parent || (r->flags & mask) != type)
+                               continue;
+                       r_size = r->end - r->start + 1;
++
++                      if ((i < PCI_BRIDGE_RESOURCES) && reassign)
++                              r_size = ALIGN(r_size, PAGE_SIZE);
++
+                       /* For bridges size != alignment */
+                       align = resource_alignment(r);
+                       order = __ffs(align) - 20;
+Index: head-2008-12-01/drivers/pci/setup-res.c
+===================================================================
+--- head-2008-12-01.orig/drivers/pci/setup-res.c       2008-12-01 10:53:15.000000000 +0100
++++ head-2008-12-01/drivers/pci/setup-res.c    2008-12-01 11:10:02.000000000 +0100
+@@ -126,6 +126,21 @@ int pci_claim_resource(struct pci_dev *d
+       return err;
+ }
++#ifdef CONFIG_PCI_REASSIGN
++void pci_disable_bridge_window(struct pci_dev *dev)
++{
++      printk(KERN_DEBUG "PCI: Disable bridge window on %s\n", pci_name(dev));
++
++      /* MMIO Base/Limit */
++      pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
++
++      /* Prefetchable MMIO Base/Limit */
++      pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
++      pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
++      pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
++}
++#endif
++
+ int pci_assign_resource(struct pci_dev *dev, int resno)
+ {
+       struct pci_bus *bus = dev->bus;
+@@ -144,6 +159,10 @@ int pci_assign_resource(struct pci_dev *
+                       (unsigned long long)res->end, res->flags);
+               return -EINVAL;
+       }
++      if (resno < PCI_BRIDGE_RESOURCES
++          && is_reassigndev(dev)
++          && (res->flags & IORESOURCE_MEM))
++              align = ALIGN(align, PAGE_SIZE);
+       /* First, try exact prefetching match.. */
+       ret = pci_bus_alloc_resource(bus, res, size, align, min,
+@@ -169,8 +188,15 @@ int pci_assign_resource(struct pci_dev *
+                       (unsigned long long)res->end);
+       } else {
+               res->flags &= ~IORESOURCE_STARTALIGN;
+-              if (resno < PCI_BRIDGE_RESOURCES)
++              if (resno < PCI_BRIDGE_RESOURCES) {
++#ifdef CONFIG_PCI_REASSIGN
++                      printk(KERN_DEBUG "PCI: Assign resource(%d) on %s "
++                              "%016llx - %016llx\n", resno, pci_name(dev),
++                              (unsigned long long)res->start,
++                              (unsigned long long)res->end);
++#endif
+                       pci_update_resource(dev, res, resno);
++              }
+       }
+       return ret;
+@@ -208,6 +234,12 @@ int pci_assign_resource_fixed(struct pci
+                       (unsigned long long)res->start,
+                       (unsigned long long)res->end);
+       } else if (resno < PCI_BRIDGE_RESOURCES) {
++#ifdef CONFIG_PCI_REASSIGN
++              printk(KERN_DEBUG "PCI: Assign resource(%d) on %s "
++                      "%016llx - %016llx\n", resno, pci_name(dev),
++                      (unsigned long long)res->start,
++                      (unsigned long long)res->end);
++#endif
+               pci_update_resource(dev, res, resno);
+       }
+@@ -220,6 +252,7 @@ EXPORT_SYMBOL_GPL(pci_assign_resource_fi
+ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+ {
+       int i;
++      int reassigndev = is_reassigndev(dev);
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               struct resource *r;
+@@ -242,12 +275,22 @@ void pdev_sort_resources(struct pci_dev 
+                               (unsigned long long)r->end, r->flags);
+                       continue;
+               }
++              if (i < PCI_BRIDGE_RESOURCES && (r->flags & IORESOURCE_MEM) &&
++                  reassigndev)
++                      r_align = ALIGN(r_align, PAGE_SIZE);
++
+               for (list = head; ; list = list->next) {
+                       resource_size_t align = 0;
+                       struct resource_list *ln = list->next;
+-                      if (ln)
++                      if (ln) {
+                               align = resource_alignment(ln->res);
++                              if (ln->res - ln->dev->resource <
++                                  PCI_BRIDGE_RESOURCES &&
++                                  (ln->res->flags & IORESOURCE_MEM) &&
++                                  is_reassigndev(ln->dev))
++                                      align = ALIGN(align, PAGE_SIZE);
++                      }
+                       if (r_align > align) {
+                               tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
diff --git a/src/patches/60005_sfc-driverlink.patch1 b/src/patches/60005_sfc-driverlink.patch1
new file mode 100644 (file)
index 0000000..7e0ac85
--- /dev/null
@@ -0,0 +1,1155 @@
+From: David Riddoch <driddoch@solarflare.com>
+commit d96c061bfd1839e34e136de0555564520acc97af
+Author: Steve Hodgson <shodgson@solarflare.com>
+Date:   Mon Jul 14 15:38:47 2008 +0100
+
+Subject: sfc: Driverlink API for exporting hardware features to client drivers
+
+References: FATE#303479
+Acked-by: jbeulich@novell.com
+
+Index: head-2008-08-18/drivers/net/sfc/Makefile
+===================================================================
+--- head-2008-08-18.orig/drivers/net/sfc/Makefile      2008-08-18 10:16:43.000000000 +0200
++++ head-2008-08-18/drivers/net/sfc/Makefile   2008-08-18 10:16:46.000000000 +0200
+@@ -1,5 +1,5 @@
+ sfc-y                 += efx.o falcon.o tx.o rx.o falcon_xmac.o \
+                          selftest.o ethtool.o xfp_phy.o \
+-                         mdio_10g.o tenxpress.o boards.o sfe4001.o
+-
++                         mdio_10g.o tenxpress.o boards.o sfe4001.o \
++                         driverlink.o
+ obj-$(CONFIG_SFC)     += sfc.o
+Index: head-2008-08-18/drivers/net/sfc/driverlink.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-08-18/drivers/net/sfc/driverlink.c       2008-08-18 10:16:46.000000000 +0200
+@@ -0,0 +1,367 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005      Fen Systems Ltd.
++ * Copyright 2005-2008 Solarflare Communications Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ */
++
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/skbuff.h>
++#include <linux/rtnetlink.h>
++#include "net_driver.h"
++#include "efx.h"
++#include "driverlink_api.h"
++#include "driverlink.h"
++
++/* Protects @efx_driverlink_lock and @efx_driver_list */
++static DEFINE_MUTEX(efx_driverlink_lock);
++
++/* List of all registered drivers */
++static LIST_HEAD(efx_driver_list);
++
++/* List of all registered Efx ports */
++static LIST_HEAD(efx_port_list);
++
++/**
++ * Driver link handle used internally to track devices
++ * @efx_dev: driverlink device handle exported to consumers
++ * @efx: efx_nic backing the driverlink device
++ * @port_node: per-device list head
++ * @driver_node: per-driver list head
++ */
++struct efx_dl_handle {
++      struct efx_dl_device efx_dev;
++      struct efx_nic *efx;
++      struct list_head port_node;
++      struct list_head driver_node;
++};
++
++static struct efx_dl_handle *efx_dl_handle(struct efx_dl_device *efx_dev)
++{
++      return container_of(efx_dev, struct efx_dl_handle, efx_dev);
++}
++
++/* Remove an Efx device, and call the driver's remove() callback if
++ * present. The caller must hold @efx_driverlink_lock. */
++static void efx_dl_del_device(struct efx_dl_device *efx_dev)
++{
++      struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++
++      EFX_INFO(efx_handle->efx, "%s driverlink client unregistering\n",
++               efx_dev->driver->name);
++
++      if (efx_dev->driver->remove)
++              efx_dev->driver->remove(efx_dev);
++
++      list_del(&efx_handle->driver_node);
++      list_del(&efx_handle->port_node);
++
++      kfree(efx_handle);
++}
++
++/* Attempt to probe the given device with the driver, creating a
++ * new &struct efx_dl_device. If the probe routine returns an error,
++ * then the &struct efx_dl_device is destroyed */
++static void efx_dl_try_add_device(struct efx_nic *efx,
++                                struct efx_dl_driver *driver)
++{
++      struct efx_dl_handle *efx_handle;
++      struct efx_dl_device *efx_dev;
++      int rc;
++
++      efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL);
++      if (!efx_handle)
++              goto fail;
++      efx_dev = &efx_handle->efx_dev;
++      efx_handle->efx = efx;
++      efx_dev->driver = driver;
++      efx_dev->pci_dev = efx->pci_dev;
++      INIT_LIST_HEAD(&efx_handle->port_node);
++      INIT_LIST_HEAD(&efx_handle->driver_node);
++
++      rc = driver->probe(efx_dev, efx->net_dev,
++                         efx->dl_info, efx->silicon_rev);
++      if (rc)
++              goto fail;
++
++      list_add_tail(&efx_handle->driver_node, &driver->device_list);
++      list_add_tail(&efx_handle->port_node, &efx->dl_device_list);
++
++      EFX_INFO(efx, "%s driverlink client registered\n", driver->name);
++      return;
++
++ fail:
++      EFX_INFO(efx, "%s driverlink client skipped\n", driver->name);
++
++      kfree(efx_handle);
++}
++
++/* Unregister a driver from the driverlink layer, calling the
++ * driver's remove() callback for every attached device */
++void efx_dl_unregister_driver(struct efx_dl_driver *driver)
++{
++      struct efx_dl_handle *efx_handle, *efx_handle_n;
++
++      printk(KERN_INFO "Efx driverlink unregistering %s driver\n",
++               driver->name);
++
++      mutex_lock(&efx_driverlink_lock);
++
++      list_for_each_entry_safe(efx_handle, efx_handle_n,
++                               &driver->device_list, driver_node)
++              efx_dl_del_device(&efx_handle->efx_dev);
++
++      list_del(&driver->node);
++
++      mutex_unlock(&efx_driverlink_lock);
++}
++EXPORT_SYMBOL(efx_dl_unregister_driver);
++
++/* Register a new driver with the driverlink layer. The driver's
++ * probe routine will be called for every attached nic. */
++int efx_dl_register_driver(struct efx_dl_driver *driver)
++{
++      struct efx_nic *efx;
++      int rc;
++
++      printk(KERN_INFO "Efx driverlink registering %s driver\n",
++               driver->name);
++
++      INIT_LIST_HEAD(&driver->node);
++      INIT_LIST_HEAD(&driver->device_list);
++
++      rc = mutex_lock_interruptible(&efx_driverlink_lock);
++      if (rc)
++              return rc;
++
++      list_add_tail(&driver->node, &efx_driver_list);
++      list_for_each_entry(efx, &efx_port_list, dl_node)
++              efx_dl_try_add_device(efx, driver);
++
++      mutex_unlock(&efx_driverlink_lock);
++
++      return 0;
++}
++EXPORT_SYMBOL(efx_dl_register_driver);
++
++void efx_dl_unregister_nic(struct efx_nic *efx)
++{
++      struct efx_dl_handle *efx_handle, *efx_handle_n;
++
++      mutex_lock(&efx_driverlink_lock);
++
++      list_for_each_entry_safe_reverse(efx_handle, efx_handle_n,
++                                       &efx->dl_device_list,
++                                       port_node)
++              efx_dl_del_device(&efx_handle->efx_dev);
++
++      list_del(&efx->dl_node);
++
++      mutex_unlock(&efx_driverlink_lock);
++}
++
++int efx_dl_register_nic(struct efx_nic *efx)
++{
++      struct efx_dl_driver *driver;
++      int rc;
++
++      rc = mutex_lock_interruptible(&efx_driverlink_lock);
++      if (rc)
++              return rc;
++
++      list_add_tail(&efx->dl_node, &efx_port_list);
++      list_for_each_entry(driver, &efx_driver_list, node)
++              efx_dl_try_add_device(efx, driver);
++
++      mutex_unlock(&efx_driverlink_lock);
++
++      return 0;
++}
++
++/* Dummy callback implementations.
++ * To avoid a branch point on the fast-path, the callbacks are always
++ * implemented - they are never NULL.
++ */
++static enum efx_veto efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev,
++                                                struct sk_buff *skb)
++{
++      return EFX_ALLOW_PACKET;
++}
++
++static enum efx_veto efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev,
++                                                const char *pkt_buf, int len)
++{
++      return EFX_ALLOW_PACKET;
++}
++
++static int efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev,
++                                        int new_mtu)
++{
++      return 0;
++}
++
++static void efx_dummy_mtu_changed_callback(struct efx_dl_device *efx_dev,
++                                         int mtu)
++{
++      return;
++}
++
++static void efx_dummy_event_callback(struct efx_dl_device *efx_dev, void *event)
++{
++      return;
++}
++
++struct efx_dl_callbacks efx_default_callbacks = {
++      .tx_packet      = efx_dummy_tx_packet_callback,
++      .rx_packet      = efx_dummy_rx_packet_callback,
++      .request_mtu    = efx_dummy_request_mtu_callback,
++      .mtu_changed    = efx_dummy_mtu_changed_callback,
++      .event          = efx_dummy_event_callback,
++};
++
++void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
++                               struct efx_dl_callbacks *callbacks)
++{
++      struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++      struct efx_nic *efx = efx_handle->efx;
++
++      efx_suspend(efx);
++
++      EFX_INFO(efx, "removing callback hooks into %s driver\n",
++               efx_dev->driver->name);
++
++      if (callbacks->tx_packet) {
++              BUG_ON(efx->dl_cb_dev.tx_packet != efx_dev);
++              efx->dl_cb.tx_packet = efx_default_callbacks.tx_packet;
++              efx->dl_cb_dev.tx_packet = NULL;
++      }
++      if (callbacks->rx_packet) {
++              BUG_ON(efx->dl_cb_dev.rx_packet != efx_dev);
++              efx->dl_cb.rx_packet = efx_default_callbacks.rx_packet;
++              efx->dl_cb_dev.rx_packet = NULL;
++      }
++      if (callbacks->request_mtu) {
++              BUG_ON(efx->dl_cb_dev.request_mtu != efx_dev);
++              efx->dl_cb.request_mtu = efx_default_callbacks.request_mtu;
++              efx->dl_cb_dev.request_mtu = NULL;
++      }
++      if (callbacks->mtu_changed) {
++              BUG_ON(efx->dl_cb_dev.mtu_changed != efx_dev);
++              efx->dl_cb.mtu_changed = efx_default_callbacks.mtu_changed;
++              efx->dl_cb_dev.mtu_changed = NULL;
++      }
++      if (callbacks->event) {
++              BUG_ON(efx->dl_cb_dev.event != efx_dev);
++              efx->dl_cb.event = efx_default_callbacks.event;
++              efx->dl_cb_dev.event = NULL;
++      }
++
++      efx_resume(efx);
++}
++EXPORT_SYMBOL(efx_dl_unregister_callbacks);
++
++int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
++                            struct efx_dl_callbacks *callbacks)
++{
++      struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++      struct efx_nic *efx = efx_handle->efx;
++      int rc = 0;
++
++      efx_suspend(efx);
++
++      /* Check that the requested callbacks are not already hooked. */
++      if ((callbacks->tx_packet && efx->dl_cb_dev.tx_packet) ||
++          (callbacks->rx_packet && efx->dl_cb_dev.rx_packet) ||
++          (callbacks->request_mtu && efx->dl_cb_dev.request_mtu) ||
++          (callbacks->mtu_changed && efx->dl_cb_dev.mtu_changed) ||
++          (callbacks->event && efx->dl_cb_dev.event)) {
++              rc = -EBUSY;
++              goto out;
++      }
++
++      EFX_INFO(efx, "adding callback hooks to %s driver\n",
++               efx_dev->driver->name);
++
++      /* Hook in the requested callbacks, leaving any NULL members
++       * referencing the members of @efx_default_callbacks */
++      if (callbacks->tx_packet) {
++              efx->dl_cb.tx_packet = callbacks->tx_packet;
++              efx->dl_cb_dev.tx_packet = efx_dev;
++      }
++      if (callbacks->rx_packet) {
++              efx->dl_cb.rx_packet = callbacks->rx_packet;
++              efx->dl_cb_dev.rx_packet = efx_dev;
++      }
++      if (callbacks->request_mtu) {
++              efx->dl_cb.request_mtu = callbacks->request_mtu;
++              efx->dl_cb_dev.request_mtu = efx_dev;
++      }
++      if (callbacks->mtu_changed) {
++              efx->dl_cb.mtu_changed = callbacks->mtu_changed;
++              efx->dl_cb_dev.mtu_changed = efx_dev;
++      }
++      if (callbacks->event) {
++              efx->dl_cb.event = callbacks->event;
++              efx->dl_cb_dev.event = efx_dev;
++      }
++
++ out:
++      efx_resume(efx);
++
++      return rc;
++}
++EXPORT_SYMBOL(efx_dl_register_callbacks);
++
++void efx_dl_schedule_reset(struct efx_dl_device *efx_dev)
++{
++      struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev);
++      struct efx_nic *efx = efx_handle->efx;
++
++      efx_schedule_reset(efx, RESET_TYPE_ALL);
++}
++EXPORT_SYMBOL(efx_dl_schedule_reset);
++
++void efx_dl_reset_unlock(void)
++{
++      mutex_unlock(&efx_driverlink_lock);
++}
++
++/* Suspend ready for reset, serialising against all the driverlink interfacse
++ * and calling the suspend() callback of every registered driver */
++void efx_dl_reset_suspend(struct efx_nic *efx)
++{
++      struct efx_dl_handle *efx_handle;
++      struct efx_dl_device *efx_dev;
++
++      mutex_lock(&efx_driverlink_lock);
++
++      list_for_each_entry_reverse(efx_handle,
++                                  &efx->dl_device_list,
++                                  port_node) {
++              efx_dev = &efx_handle->efx_dev;
++              if (efx_dev->driver->reset_suspend)
++                      efx_dev->driver->reset_suspend(efx_dev);
++      }
++}
++
++/* Resume after a reset, calling the resume() callback of every registered
++ * driver, and releasing @Efx_driverlink_lock acquired in
++ * efx_dl_reset_resume() */
++void efx_dl_reset_resume(struct efx_nic *efx, int ok)
++{
++      struct efx_dl_handle *efx_handle;
++      struct efx_dl_device *efx_dev;
++
++      list_for_each_entry(efx_handle, &efx->dl_device_list,
++                          port_node) {
++              efx_dev = &efx_handle->efx_dev;
++              if (efx_dev->driver->reset_resume)
++                      efx_dev->driver->reset_resume(efx_dev, ok);
++      }
++
++      mutex_unlock(&efx_driverlink_lock);
++}
+Index: head-2008-08-18/drivers/net/sfc/driverlink.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-08-18/drivers/net/sfc/driverlink.h       2008-08-18 10:16:46.000000000 +0200
+@@ -0,0 +1,43 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005      Fen Systems Ltd.
++ * Copyright 2006-2008 Solarflare Communications Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ */
++
++#ifndef EFX_DRIVERLINK_H
++#define EFX_DRIVERLINK_H
++
++/* Forward declarations */
++struct efx_dl_device;
++struct efx_nic;
++
++/* Efx callback devices
++ *
++ * A list of the devices that own each callback. The partner to
++ * struct efx_dl_callbacks.
++ */
++struct efx_dl_cb_devices {
++      struct efx_dl_device *tx_packet;
++      struct efx_dl_device *rx_packet;
++      struct efx_dl_device *request_mtu;
++      struct efx_dl_device *mtu_changed;
++      struct efx_dl_device *event;
++};
++
++extern struct efx_dl_callbacks efx_default_callbacks;
++
++#define EFX_DL_CALLBACK(_port, _name, ...)                            \
++      (_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__)
++
++extern int efx_dl_register_nic(struct efx_nic *efx);
++extern void efx_dl_unregister_nic(struct efx_nic *efx);
++
++/* Suspend and resume client drivers over a hardware reset */
++extern void efx_dl_reset_suspend(struct efx_nic *efx);
++extern void efx_dl_reset_resume(struct efx_nic *efx, int ok);
++
++#endif /* EFX_DRIVERLINK_H */
+Index: head-2008-08-18/drivers/net/sfc/driverlink_api.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-08-18/drivers/net/sfc/driverlink_api.h   2008-08-18 10:16:46.000000000 +0200
+@@ -0,0 +1,303 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2005-2008 Solarflare Communications Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ */
++
++#ifndef EFX_DRIVERLINK_API_H
++#define EFX_DRIVERLINK_API_H
++
++#include <linux/list.h>
++
++/* Forward declarations */
++struct pci_dev;
++struct net_device;
++struct sk_buff;
++struct efx_dl_device;
++struct efx_dl_device_info;
++
++/* An extra safeguard in addition to symbol versioning */
++#define EFX_DRIVERLINK_API_VERSION 2
++
++/**
++ * struct efx_dl_driver - An Efx driverlink device driver
++ *
++ * A driverlink client defines and initializes as many instances of
++ * efx_dl_driver as required, registering each one with
++ * efx_dl_register_driver().
++ *
++ * @name: Name of the driver
++ * @probe: Called when device added
++ *    The client should use the @def_info linked list and @silicon_rev
++ *    to determine if they wish to attach to this device.
++ *    Context: process, driverlink semaphore held
++ * @remove: Called when device removed
++ *    The client must ensure the finish all operations with this
++ *    device before returning from this method.
++ *    Context: process, driverlink semaphore held
++ * @reset_suspend: Called before device is reset
++ *    Called immediately before a hardware reset. The client must stop all
++ *    hardware processing before returning from this method. Callbacks will
++ *    be inactive when this method is called.
++ *    Context: process, driverlink semaphore held. rtnl_lock may be held
++ * @reset_resume: Called after device is reset
++ *    Called after a hardware reset. If @ok is true, the client should
++ *    state and resume normal operations. If @ok is false, the client should
++ *    abandon use of the hardware resources. remove() will still be called.
++ *    Context: process, driverlink semaphore held. rtnl_lock may be held
++ */
++struct efx_dl_driver {
++      const char *name;
++
++      int (*probe) (struct efx_dl_device *efx_dl_dev,
++                    const struct net_device *net_dev,
++                    const struct efx_dl_device_info *dev_info,
++                    const char *silicon_rev);
++      void (*remove) (struct efx_dl_device *efx_dev);
++      void (*reset_suspend) (struct efx_dl_device *efx_dev);
++      void (*reset_resume) (struct efx_dl_device *efx_dev, int ok);
++
++/* private: */
++      struct list_head node;
++      struct list_head device_list;
++};
++
++/**
++ * enum efx_dl_device_info_type - Device information identifier.
++ *
++ * Used to identify each item in the &struct efx_dl_device_info linked list
++ * provided to each driverlink client in the probe() @dev_info member.
++ *
++ * @EFX_DL_FALCON_RESOURCES: Information type is &struct efx_dl_falcon_resources
++ */
++enum efx_dl_device_info_type {
++      /** Falcon resources available for export */
++      EFX_DL_FALCON_RESOURCES = 0,
++};
++
++/**
++ * struct efx_dl_device_info - device information structure
++ *
++ * @next: Link to next structure, if any
++ * @type: Type code for this structure
++ */
++struct efx_dl_device_info {
++      struct efx_dl_device_info *next;
++      enum efx_dl_device_info_type type;
++};
++
++/**
++ * enum efx_dl_falcon_resource_flags - Falcon resource information flags.
++ *
++ * Flags that describe hardware variations for the current Falcon device.
++ *
++ * @EFX_DL_FALCON_DUAL_FUNC: Port is dual-function.
++ *    Certain silicon revisions have two pci functions, and require
++ *    certain hardware resources to be accessed via the secondary
++ *    function
++ * @EFX_DL_FALCON_USE_MSI: Port is initialised to use MSI/MSI-X interrupts.
++ *    Falcon supports traditional legacy interrupts and MSI/MSI-X
++ *    interrupts. The choice is made at run time by the sfc driver, and
++ *    notified to the clients by this enumeration
++ */
++enum efx_dl_falcon_resource_flags {
++      EFX_DL_FALCON_DUAL_FUNC = 0x1,
++      EFX_DL_FALCON_USE_MSI = 0x2,
++};
++
++/**
++ * struct efx_dl_falcon_resources - Falcon resource information.
++ *
++ * This structure describes Falcon hardware resources available for
++ * use by a driverlink driver.
++ *
++ * @hdr: Resource linked list header
++ * @biu_lock: Register access lock.
++ *    Some Falcon revisions require register access for configuration
++ *    registers to be serialised between ports and PCI functions.
++ *    The sfc driver will provide the appropriate lock semantics for
++ *    the underlying hardware.
++ * @buffer_table_min: First available buffer table entry
++ * @buffer_table_lim: Last available buffer table entry + 1
++ * @evq_timer_min: First available event queue with timer
++ * @evq_timer_lim: Last available event queue with timer + 1
++ * @evq_int_min: First available event queue with interrupt
++ * @evq_int_lim: Last available event queue with interrupt + 1
++ * @rxq_min: First available RX queue
++ * @rxq_lim: Last available RX queue + 1
++ * @txq_min: First available TX queue
++ * @txq_lim: Last available TX queue + 1
++ * @flags: Hardware variation flags
++ */
++struct efx_dl_falcon_resources {
++      struct efx_dl_device_info hdr;
++      spinlock_t *biu_lock;
++      unsigned buffer_table_min;
++      unsigned buffer_table_lim;
++      unsigned evq_timer_min;
++      unsigned evq_timer_lim;
++      unsigned evq_int_min;
++      unsigned evq_int_lim;
++      unsigned rxq_min;
++      unsigned rxq_lim;
++      unsigned txq_min;
++      unsigned txq_lim;
++      enum efx_dl_falcon_resource_flags flags;
++};
++
++/**
++ * struct efx_dl_device - An Efx driverlink device.
++ *
++ * @pci_dev: PCI device used by the sfc driver.
++ * @priv: Driver private data
++ *    Driverlink clients can use this to store a pointer to their
++ *    internal per-device data structure. Each (driver, device)
++ *    tuple has a separate &struct efx_dl_device, so clients can use
++ *    this @priv field independently.
++ * @driver: Efx driverlink driver for this device
++ */
++struct efx_dl_device {
++      struct pci_dev *pci_dev;
++      void *priv;
++      struct efx_dl_driver *driver;
++};
++
++/**
++ * enum efx_veto - Packet veto request flag.
++ *
++ * This is the return type for the rx_packet() and tx_packet() methods
++ * in &struct efx_dl_callbacks.
++ *
++ * @EFX_ALLOW_PACKET: Packet may be transmitted/received
++ * @EFX_VETO_PACKET: Packet must not be transmitted/received
++ */
++enum efx_veto {
++      EFX_ALLOW_PACKET = 0,
++      EFX_VETO_PACKET = 1,
++};
++
++/**
++ * struct efx_dl_callbacks - Efx callbacks
++ *
++ * This is a tighly controlled set of simple callbacks, that are attached
++ * to the sfc driver via efx_dl_register_callbacks().  They export just enough
++ * state to allow clients to make use of the available hardware resources.
++ *
++ * For efficiency, only one client can hook each callback. Since these
++ * callbacks are called on packet transmit and reception paths, and the
++ * sfc driver may have multiple tx and rx queues per port, clients should
++ * avoid acquiring locks or allocating memory.
++ *
++ * @tx_packet: Called when packet is about to be transmitted
++ *    Called for every packet about to be transmitted, providing means
++ *    for the client to snoop traffic, and veto transmission by returning
++ *    %EFX_VETO_PACKET (the sfc driver will subsequently free the skb).
++ *    Context: tasklet, netif_tx_lock held
++ * @rx_packet: Called when packet is received
++ *    Called for every received packet (after LRO), allowing the client
++ *    to snoop every received packet (on every rx queue), and veto
++ *    reception by returning %EFX_VETO_PACKET.
++ *    Context: tasklet
++ * @request_mtu: Called to request MTU change.
++ *    Called whenever the user requests the net_dev mtu to be changed.
++ *    If the client returns an error, the mtu change is aborted. The sfc
++ *    driver guarantees that no other callbacks are running.
++ *    Context: process, rtnl_lock held.
++ * @mtu_changed: Called when MTU has been changed.
++ *    Called after the mtu has been successfully changed, always after
++ *    a previous call to request_mtu(). The sfc driver guarantees that no
++ *    other callbacks are running.
++ *    Context: process, rtnl_lock held.
++ * @event: Called when a hardware NIC event is not understood by the sfc driver.
++ *    Context: tasklet.
++ */
++struct efx_dl_callbacks {
++      enum efx_veto (*tx_packet) (struct efx_dl_device *efx_dev,
++                                  struct sk_buff *skb);
++      enum efx_veto (*rx_packet) (struct efx_dl_device *efx_dev,
++                                  const char *pkt_hdr, int pkt_len);
++      int (*request_mtu) (struct efx_dl_device *efx_dev, int new_mtu);
++      void (*mtu_changed) (struct efx_dl_device *efx_dev, int mtu);
++      void (*event) (struct efx_dl_device *efx_dev, void *p_event);
++};
++
++/* Include API version number in symbol used for efx_dl_register_driver */
++#define efx_dl_stringify_1(x, y) x ## y
++#define efx_dl_stringify_2(x, y) efx_dl_stringify_1(x, y)
++#define efx_dl_register_driver                                        \
++      efx_dl_stringify_2(efx_dl_register_driver_api_ver_,     \
++                         EFX_DRIVERLINK_API_VERSION)
++
++/* Exported driverlink api used to register and unregister the client driver
++ * and any callbacks [only one per port allowed], and to allow a client driver
++ * to request reset to recover from an error condition.
++ *
++ * All of these functions acquire the driverlink semaphore, so must not be
++ * called from an efx_dl_driver or efx_dl_callbacks member, and must be called
++ * from process context.
++ */
++extern int efx_dl_register_driver(struct efx_dl_driver *driver);
++
++extern void efx_dl_unregister_driver(struct efx_dl_driver *driver);
++
++extern int efx_dl_register_callbacks(struct efx_dl_device *efx_dev,
++                                   struct efx_dl_callbacks *callbacks);
++
++extern void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev,
++                                      struct efx_dl_callbacks *callbacks);
++
++/* Schedule a reset without grabbing any locks */
++extern void efx_dl_schedule_reset(struct efx_dl_device *efx_dev);
++
++/**
++ * efx_dl_for_each_device_info_matching - iterate an efx_dl_device_info list
++ * @_dev_info: Pointer to first &struct efx_dl_device_info
++ * @_type: Type code to look for
++ * @_info_type: Structure type corresponding to type code
++ * @_field: Name of &struct efx_dl_device_info field in the type
++ * @_p: Iterator variable
++ *
++ * Example:
++ *    struct efx_dl_falcon_resources *res;
++ *    efx_dl_for_each_device_info_matching(dev_info, EFX_DL_FALCON_RESOURCES,
++ *                                         struct efx_dl_falcon_resources,
++ *                                         hdr, res) {
++ *            if (res->flags & EFX_DL_FALCON_DUAL_FUNC)
++ *                    ....
++ *    }
++ */
++#define efx_dl_for_each_device_info_matching(_dev_info, _type,                \
++                                           _info_type, _field, _p)    \
++      for ((_p) = container_of((_dev_info), _info_type, _field);      \
++           (_p) != NULL;                                              \
++           (_p) = container_of((_p)->_field.next, _info_type, _field))\
++              if ((_p)->_field.type != _type)                         \
++                      continue;                                       \
++              else
++
++/**
++ * efx_dl_search_device_info - search an efx_dl_device_info list
++ * @_dev_info: Pointer to first &struct efx_dl_device_info
++ * @_type: Type code to look for
++ * @_info_type: Structure type corresponding to type code
++ * @_field: Name of &struct efx_dl_device_info member in this type
++ * @_p: Result variable
++ *
++ * Example:
++ *    struct efx_dl_falcon_resources *res;
++ *    efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
++ *                              struct efx_dl_falcon_resources, hdr, res);
++ *    if (res)
++ *            ....
++ */
++#define efx_dl_search_device_info(_dev_info, _type, _info_type,               \
++                                _field, _p)                           \
++      efx_dl_for_each_device_info_matching((_dev_info), (_type),      \
++                                           _info_type, _field, (_p))  \
++              break;
++
++#endif /* EFX_DRIVERLINK_API_H */
+Index: head-2008-08-18/drivers/net/sfc/efx.c
+===================================================================
+--- head-2008-08-18.orig/drivers/net/sfc/efx.c 2008-08-18 10:16:43.000000000 +0200
++++ head-2008-08-18/drivers/net/sfc/efx.c      2008-08-18 10:16:46.000000000 +0200
+@@ -1427,6 +1427,11 @@ static int efx_change_mtu(struct net_dev
+       efx_stop_all(efx);
++      /* Ask driverlink client if we can change MTU */
++      rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu);
++      if (rc)
++              goto out;
++
+       EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
+       efx_fini_channels(efx);
+@@ -1435,6 +1440,10 @@ static int efx_change_mtu(struct net_dev
+       if (rc)
+               goto fail;
++      /* Notify driverlink client of new MTU */
++      EFX_DL_CALLBACK(efx, mtu_changed, new_mtu);
++
++ out:
+       efx_start_all(efx);
+       return rc;
+@@ -1587,6 +1596,23 @@ static void efx_unregister_netdev(struct
+  * Device reset and suspend
+  *
+  **************************************************************************/
++/* Serialise access to the driverlink callbacks, by quiescing event processing
++ * (without flushing the descriptor queues), and acquiring the rtnl_lock */
++void efx_suspend(struct efx_nic *efx)
++{
++      EFX_LOG(efx, "suspending operations\n");
++
++      rtnl_lock();
++      efx_stop_all(efx);
++}
++
++void efx_resume(struct efx_nic *efx)
++{
++      EFX_LOG(efx, "resuming operations\n");
++
++      efx_start_all(efx);
++      rtnl_unlock();
++}
+ /* The final hardware and software finalisation before reset. */
+ static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+@@ -1649,8 +1675,8 @@ static int efx_reset(struct efx_nic *efx
+       enum reset_type method = efx->reset_pending;
+       int rc;
+-      /* Serialise with kernel interfaces */
+       rtnl_lock();
++      efx_dl_reset_suspend(efx);
+       /* If we're not RUNNING then don't reset. Leave the reset_pending
+        * flag set so that efx_pci_probe_main will be retried */
+@@ -1717,6 +1743,7 @@ static int efx_reset(struct efx_nic *efx
+       efx_start_all(efx);
+  unlock_rtnl:
++      efx_dl_reset_resume(efx, 1);
+       rtnl_unlock();
+       return 0;
+@@ -1729,6 +1756,7 @@ static int efx_reset(struct efx_nic *efx
+       efx->state = STATE_DISABLED;
+       mutex_unlock(&efx->mac_lock);
++      efx_dl_reset_resume(efx, 0);
+       rtnl_unlock();
+       efx_unregister_netdev(efx);
+       efx_fini_port(efx);
+@@ -1871,6 +1899,9 @@ static int efx_init_struct(struct efx_ni
+       mutex_init(&efx->mac_lock);
+       efx->phy_op = &efx_dummy_phy_operations;
+       efx->mii.dev = net_dev;
++      INIT_LIST_HEAD(&efx->dl_node);
++      INIT_LIST_HEAD(&efx->dl_device_list);
++      efx->dl_cb = efx_default_callbacks;
+       INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work);
+       atomic_set(&efx->netif_stop_count, 1);
+@@ -1990,6 +2021,7 @@ static void efx_pci_remove(struct pci_de
+       efx = pci_get_drvdata(pci_dev);
+       if (!efx)
+               return;
++      efx_dl_unregister_nic(efx);
+       /* Mark the NIC as fini, then stop the interface */
+       rtnl_lock();
+@@ -2157,8 +2189,15 @@ static int __devinit efx_pci_probe(struc
+       EFX_LOG(efx, "initialisation successful\n");
++      /* Register with driverlink layer */
++      rc = efx_dl_register_nic(efx);
++      if (rc)
++              goto fail6;
++
+       return 0;
++ fail6:
++      efx_unregister_netdev(efx);
+  fail5:
+       efx_pci_remove_main(efx);
+  fail4:
+Index: head-2008-08-18/drivers/net/sfc/falcon.c
+===================================================================
+--- head-2008-08-18.orig/drivers/net/sfc/falcon.c      2008-08-18 10:16:43.000000000 +0200
++++ head-2008-08-18/drivers/net/sfc/falcon.c   2008-08-18 10:16:46.000000000 +0200
+@@ -36,12 +36,12 @@
+ /**
+  * struct falcon_nic_data - Falcon NIC state
+- * @next_buffer_table: First available buffer table id
++ * @resources: Resource information for driverlink client
+  * @pci_dev2: The secondary PCI device if present
+  * @i2c_data: Operations and state for I2C bit-bashing algorithm
+  */
+ struct falcon_nic_data {
+-      unsigned next_buffer_table;
++      struct efx_dl_falcon_resources resources;
+       struct pci_dev *pci_dev2;
+       struct i2c_algo_bit_data i2c_data;
+ };
+@@ -322,8 +322,8 @@ static int falcon_alloc_special_buffer(s
+       memset(buffer->addr, 0xff, len);
+       /* Select new buffer ID */
+-      buffer->index = nic_data->next_buffer_table;
+-      nic_data->next_buffer_table += buffer->entries;
++      buffer->index = nic_data->resources.buffer_table_min;
++      nic_data->resources.buffer_table_min += buffer->entries;
+       EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
+               "(virt %p phys %lx)\n", buffer->index,
+@@ -1115,10 +1115,12 @@ static void falcon_handle_driver_event(s
+       case TX_DESCQ_FLS_DONE_EV_DECODE:
+               EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
+                         channel->channel, ev_sub_data);
++              EFX_DL_CALLBACK(efx, event, event);
+               break;
+       case RX_DESCQ_FLS_DONE_EV_DECODE:
+               EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
+                         channel->channel, ev_sub_data);
++              EFX_DL_CALLBACK(efx, event, event);
+               break;
+       case EVQ_INIT_DONE_EV_DECODE:
+               EFX_LOG(efx, "channel %d EVQ %d initialised\n",
+@@ -1127,14 +1129,17 @@ static void falcon_handle_driver_event(s
+       case SRM_UPD_DONE_EV_DECODE:
+               EFX_TRACE(efx, "channel %d SRAM update done\n",
+                         channel->channel);
++              EFX_DL_CALLBACK(efx, event, event);
+               break;
+       case WAKE_UP_EV_DECODE:
+               EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
+                         channel->channel, ev_sub_data);
++              EFX_DL_CALLBACK(efx, event, event);
+               break;
+       case TIMER_EV_DECODE:
+               EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
+                         channel->channel, ev_sub_data);
++              EFX_DL_CALLBACK(efx, event, event);
+               break;
+       case RX_RECOVERY_EV_DECODE:
+               EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
+@@ -1159,6 +1164,7 @@ static void falcon_handle_driver_event(s
+               EFX_TRACE(efx, "channel %d unknown driver event code %d "
+                         "data %04x\n", channel->channel, ev_sub_code,
+                         ev_sub_data);
++              EFX_DL_CALLBACK(efx, event, event);
+               break;
+       }
+ }
+@@ -2371,6 +2377,59 @@ static int falcon_probe_nvconfig(struct 
+       return rc;
+ }
++/* Looks at available SRAM resources and silicon revision, and works out
++ * how many queues we can support, and where things like descriptor caches
++ * should live. */
++static int falcon_dimension_resources(struct efx_nic *efx)
++{
++      unsigned internal_dcs_entries;
++      struct falcon_nic_data *nic_data = efx->nic_data;
++      struct efx_dl_falcon_resources *res = &nic_data->resources;
++
++      /* Fill out the driverlink resource list */
++      res->hdr.type = EFX_DL_FALCON_RESOURCES;
++      res->biu_lock = &efx->biu_lock;
++      efx->dl_info = &res->hdr;
++
++      /* NB. The minimum values get increased as this driver initialises
++       * its resources, so this should prevent any overlap.
++       */
++      switch (falcon_rev(efx)) {
++      case FALCON_REV_A1:
++              res->rxq_min = 16;
++              res->txq_min = 16;
++              res->evq_int_min = 4;
++              res->evq_int_lim = 5;
++              res->evq_timer_min = 5;
++              res->evq_timer_lim = 4096;
++              internal_dcs_entries = 8192;
++              break;
++      case FALCON_REV_B0:
++      default:
++              res->rxq_min = 0;
++              res->txq_min = 0;
++              res->evq_int_min = 0;
++              res->evq_int_lim = 64;
++              res->evq_timer_min = 64;
++              res->evq_timer_lim = 4096;
++              internal_dcs_entries = 4096;
++              break;
++      }
++
++      /* Internal SRAM only for now */
++      res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES;
++      res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES;
++      res->buffer_table_lim = 8192;
++
++      if (FALCON_IS_DUAL_FUNC(efx))
++              res->flags |= EFX_DL_FALCON_DUAL_FUNC;
++
++      if (EFX_INT_MODE_USE_MSI(efx))
++              res->flags |= EFX_DL_FALCON_USE_MSI;
++
++      return 0;
++}
++
+ /* Probe the NIC variant (revision, ASIC vs FPGA, function count, port
+  * count, port speed).  Set workaround and feature flags accordingly.
+  */
+@@ -2403,10 +2462,12 @@ static int falcon_probe_nic_variant(stru
+                       EFX_ERR(efx, "1G mode not supported\n");
+                       return -ENODEV;
+               }
++              efx->silicon_rev = "falcon/a1";
+               break;
+       }
+       case FALCON_REV_B0:
++              efx->silicon_rev = "falcon/b0";
+               break;
+       default:
+@@ -2472,6 +2533,10 @@ int falcon_probe_nic(struct efx_nic *efx
+       if (rc)
+               goto fail5;
++      rc = falcon_dimension_resources(efx);
++      if (rc)
++              goto fail6;
++
+       /* Initialise I2C adapter */
+       efx->i2c_adap.owner = THIS_MODULE;
+       nic_data->i2c_data = falcon_i2c_bit_operations;
+@@ -2481,10 +2546,12 @@ int falcon_probe_nic(struct efx_nic *efx
+       strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
+       rc = i2c_bit_add_bus(&efx->i2c_adap);
+       if (rc)
+-              goto fail5;
++              goto fail6;
+       return 0;
++ fail6:
++      efx->dl_info = NULL;
+  fail5:
+       falcon_free_buffer(efx, &efx->irq_status);
+  fail4:
+@@ -2675,6 +2742,7 @@ void falcon_remove_nic(struct efx_nic *e
+       /* Tear down the private nic state */
+       kfree(efx->nic_data);
+       efx->nic_data = NULL;
++      efx->dl_info = NULL;
+ }
+ void falcon_update_nic_stats(struct efx_nic *efx)
+Index: head-2008-08-18/drivers/net/sfc/net_driver.h
+===================================================================
+--- head-2008-08-18.orig/drivers/net/sfc/net_driver.h  2008-08-18 10:16:43.000000000 +0200
++++ head-2008-08-18/drivers/net/sfc/net_driver.h       2008-08-18 10:16:46.000000000 +0200
+@@ -30,6 +30,8 @@
+ #include "enum.h"
+ #include "bitfield.h"
++#include "driverlink_api.h"
++#include "driverlink.h"
+ #define EFX_MAX_LRO_DESCRIPTORS 8
+ #define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS
+@@ -676,6 +678,12 @@ union efx_multicast_hash {
+  * @loopback_mode: Loopback status
+  * @loopback_modes: Supported loopback mode bitmask
+  * @loopback_selftest: Offline self-test private state
++ * @silicon_rev: Silicon revision description for driverlink
++ * @dl_info: Linked list of hardware parameters exposed through driverlink
++ * @dl_node: Driverlink port list
++ * @dl_device_list: Driverlink device list
++ * @dl_cb: Driverlink callbacks table
++ * @dl_cb_dev: Driverlink callback owner devices
+  *
+  * The @priv field of the corresponding &struct net_device points to
+  * this.
+@@ -752,6 +760,13 @@ struct efx_nic {
+       unsigned int loopback_modes;
+       void *loopback_selftest;
++
++      const char *silicon_rev;
++      struct efx_dl_device_info *dl_info;
++      struct list_head dl_node;
++      struct list_head dl_device_list;
++      struct efx_dl_callbacks dl_cb;
++      struct efx_dl_cb_devices dl_cb_dev;
+ };
+ static inline int efx_dev_registered(struct efx_nic *efx)
+Index: head-2008-08-18/drivers/net/sfc/rx.c
+===================================================================
+--- head-2008-08-18.orig/drivers/net/sfc/rx.c  2008-08-18 10:16:43.000000000 +0200
++++ head-2008-08-18/drivers/net/sfc/rx.c       2008-08-18 10:16:46.000000000 +0200
+@@ -549,8 +549,22 @@ static inline void efx_rx_packet__check_
+ static inline void efx_rx_packet_lro(struct efx_channel *channel,
+                                    struct efx_rx_buffer *rx_buf)
+ {
++      struct efx_nic *efx = channel->efx;
+       struct net_lro_mgr *lro_mgr = &channel->lro_mgr;
+       void *priv = channel;
++      enum efx_veto veto;
++
++      /* It would be faster if we had access to packets at the
++       * other side of generic LRO. Unfortunately, there isn't
++       * an obvious interface to this, so veto packets before LRO */
++      veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
++      if (unlikely(veto)) {
++              EFX_TRACE(efx, "LRO RX vetoed by driverlink %s driver\n",
++                        efx->dl_cb_dev.rx_packet->driver->name);
++              /* Free the buffer now */
++              efx_free_rx_buffer(efx, rx_buf);
++              return;
++      }
+       /* Pass the skb/page into the LRO engine */
+       if (rx_buf->page) {
+@@ -686,6 +700,7 @@ void __efx_rx_packet(struct efx_channel 
+                    struct efx_rx_buffer *rx_buf, int checksummed)
+ {
+       struct efx_nic *efx = channel->efx;
++      enum efx_veto veto;
+       struct sk_buff *skb;
+       int lro = efx->net_dev->features & NETIF_F_LRO;
+@@ -723,6 +738,16 @@ void __efx_rx_packet(struct efx_channel 
+               goto done;
+       }
++      /* Allow callback to veto the packet */
++      veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
++      if (unlikely(veto)) {
++              EFX_LOG(efx, "RX vetoed by driverlink %s driver\n",
++                      efx->dl_cb_dev.rx_packet->driver->name);
++              /* Free the buffer now */
++              efx_free_rx_buffer(efx, rx_buf);
++              goto done;
++      }
++
+       /* Form an skb if required */
+       if (rx_buf->page) {
+               int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS);
+Index: head-2008-08-18/drivers/net/sfc/tx.c
+===================================================================
+--- head-2008-08-18.orig/drivers/net/sfc/tx.c  2008-08-18 10:16:43.000000000 +0200
++++ head-2008-08-18/drivers/net/sfc/tx.c       2008-08-18 10:16:46.000000000 +0200
+@@ -368,7 +368,21 @@ inline int efx_xmit(struct efx_nic *efx,
+ int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
+ {
+       struct efx_nic *efx = net_dev->priv;
+-      return efx_xmit(efx, &efx->tx_queue[0], skb);
++      struct efx_tx_queue *tx_queue = &efx->tx_queue[0];
++      enum efx_veto veto;
++
++      /* See if driverlink wants to veto the packet. */
++      veto = EFX_DL_CALLBACK(efx, tx_packet, skb);
++      if (unlikely(veto)) {
++              EFX_TRACE(efx, "TX queue %d packet vetoed by "
++                        "driverlink %s driver\n", tx_queue->queue,
++                        efx->dl_cb_dev.tx_packet->driver->name);
++              /* Free the skb; nothing else will do it */
++              dev_kfree_skb_any(skb);
++              return NETDEV_TX_OK;
++      }
++
++      return efx_xmit(efx, tx_queue, skb);
+ }
+ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
diff --git a/src/patches/60006_sfc-resource-driver.patch1 b/src/patches/60006_sfc-resource-driver.patch1
new file mode 100644 (file)
index 0000000..29dac94
--- /dev/null
@@ -0,0 +1,15194 @@
+From: David Riddoch <driddoch@solarflare.com>
+# replaces http://xenbits.xensource.com/linux-2.6.18-xen.hg c/s 421:
+# HG changeset patch
+# User Keir Fraser <keir.fraser@citrix.com>
+# Date 1203330569 0
+# Node ID e4dd072db2595c420bb21d9e835416f4fd543526
+# Parent  fc90e9b2c12b316b5460ece28f013e6de881af1a
+Subject: Solarflare: Resource driver.
+References: FATE#303479
+Acked-by: jbeulich@novell.com
+
+Index: head-2008-07-15/drivers/net/sfc/Kconfig
+===================================================================
+--- head-2008-07-15.orig/drivers/net/sfc/Kconfig       2008-07-17 16:17:36.000000000 +0200
++++ head-2008-07-15/drivers/net/sfc/Kconfig    2008-07-17 16:18:07.000000000 +0200
+@@ -12,3 +12,9 @@ config SFC
+         To compile this driver as a module, choose M here.  The module
+         will be called sfc.
++
++config SFC_RESOURCE
++      depends on SFC && X86
++      tristate "Solarflare Solarstorm SFC4000 resource driver"
++      help
++        This module provides the SFC resource manager driver.
+Index: head-2008-07-15/drivers/net/sfc/Makefile
+===================================================================
+--- head-2008-07-15.orig/drivers/net/sfc/Makefile      2008-07-17 16:17:53.000000000 +0200
++++ head-2008-07-15/drivers/net/sfc/Makefile   2008-07-17 16:18:07.000000000 +0200
+@@ -3,3 +3,5 @@ sfc-y                  += efx.o falcon.o tx.o rx.o falc
+                          mdio_10g.o tenxpress.o boards.o sfe4001.o \
+                          driverlink.o
+ obj-$(CONFIG_SFC)     += sfc.o
++
++obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/Makefile
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/Makefile      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,14 @@
++obj-$(CONFIG_SFC_RESOURCE) := sfc_resource.o
++
++EXTRA_CFLAGS += -D__CI_HARDWARE_CONFIG_FALCON__
++EXTRA_CFLAGS += -D__ci_driver__
++EXTRA_CFLAGS += -Werror
++EXTRA_CFLAGS += -Idrivers/net/sfc -Idrivers/net/sfc/sfc_resource
++
++sfc_resource-objs := resource_driver.o iopage.o efx_vi_shm.o \
++      driverlink_new.o kernel_proc.o kfifo.o \
++      nic.o eventq.o falcon.o falcon_hash.o \
++      assert_valid.o buddy.o buffer_table.o filter_resource.o \
++      iobufset_resource.o resource_manager.o resources.o \
++      vi_resource_alloc.o vi_resource_event.o vi_resource_flush.o \
++      vi_resource_manager.o driver_object.o kernel_compat.o
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/assert_valid.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/assert_valid.c        2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,92 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains functions to assert validness of resources and
++ * resource manager in DEBUG build of the resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/sysdep.h>
++
++#ifndef NDEBUG
++#include <ci/efrm/resource.h>
++#include <ci/efrm/driver_private.h>
++#include <ci/efrm/debug.h>
++
++void
++efrm_resource_manager_assert_valid(struct efrm_resource_manager *rm,
++                                 const char *file, int line)
++{
++      _EFRM_ASSERT(rm, file, line);
++      _EFRM_ASSERT(rm->rm_name, file, line);
++      _EFRM_ASSERT(rm->rm_type < EFRM_RESOURCE_NUM, file, line);
++      _EFRM_ASSERT(rm->rm_dtor, file, line);
++}
++EXPORT_SYMBOL(efrm_resource_manager_assert_valid);
++
++/*
++ * \param rs                    resource to validate
++ * \param ref_count_is_zero     One of 3 values
++ *                                > 0  - check ref count is zero
++ *                                = 0  - check ref count is non-zero
++ *                                < 0  - ref count could be any value
++ */
++void
++efrm_resource_assert_valid(struct efrm_resource *rs, int ref_count_is_zero,
++                         const char *file, int line)
++{
++      struct efrm_resource_manager *rm;
++
++      _EFRM_ASSERT(rs, file, line);
++
++      if (ref_count_is_zero >= 0) {
++              if (!(ref_count_is_zero || rs->rs_ref_count > 0)
++                  || !(!ref_count_is_zero || rs->rs_ref_count == 0))
++                      EFRM_WARN("%s: check %szero ref=%d " EFRM_RESOURCE_FMT,
++                                __func__,
++                                ref_count_is_zero == 0 ? "non-" : "",
++                                rs->rs_ref_count,
++                                EFRM_RESOURCE_PRI_ARG(rs->rs_handle));
++
++              _EFRM_ASSERT(!(ref_count_is_zero == 0) ||
++                           rs->rs_ref_count != 0, file, line);
++              _EFRM_ASSERT(!(ref_count_is_zero > 0) ||
++                           rs->rs_ref_count == 0, file, line);
++      }
++
++      rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
++      efrm_resource_manager_assert_valid(rm, file, line);
++}
++EXPORT_SYMBOL(efrm_resource_assert_valid);
++
++#endif
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/buddy.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/buddy.c       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,220 @@
++
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains implementation of a buddy allocator.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#include <ci/efhw/common.h> /* get uintXX types on win32 */
++#include <ci/efrm/sysdep.h>
++#include <ci/efrm/buddy.h>
++#include <ci/efrm/debug.h>
++
++#if 1
++#define DEBUG_ALLOC(x)
++#else
++#define DEBUG_ALLOC(x) x
++
++static inline void efrm_buddy_dump(struct efrm_buddy_allocator *b)
++{
++      unsigned o;
++
++      EFRM_NOTICE("%s: dump allocator with order %u",
++                  __func__, b->order);
++      for (o = 0; o <= b->order; o++) {
++              struct list_head *l = &b->free_lists[o];
++              while (l->next != &b->free_lists[o]) {
++                      l = l->next;
++                      EFRM_NOTICE("%s: order %x: %zx", __func__, o,
++                                  l - b->links);
++              }
++      }
++}
++#endif
++
++/*
++ * The purpose of the following inline functions is to give the
++ * understandable names to the simple actions.
++ */
++static inline void
++efrm_buddy_free_list_add(struct efrm_buddy_allocator *b,
++                       unsigned order, unsigned addr)
++{
++      list_add(&b->links[addr], &b->free_lists[order]);
++      b->orders[addr] = (uint8_t) order;
++}
++static inline void
++efrm_buddy_free_list_del(struct efrm_buddy_allocator *b, unsigned addr)
++{
++      list_del(&b->links[addr]);
++      b->links[addr].next = NULL;
++}
++static inline int
++efrm_buddy_free_list_empty(struct efrm_buddy_allocator *b, unsigned order)
++{
++      return list_empty(&b->free_lists[order]);
++}
++static inline unsigned
++efrm_buddy_free_list_pop(struct efrm_buddy_allocator *b, unsigned order)
++{
++      struct list_head *l = list_pop(&b->free_lists[order]);
++      l->next = NULL;
++      return (unsigned)(l - b->links);
++}
++static inline int
++efrm_buddy_addr_in_free_list(struct efrm_buddy_allocator *b, unsigned addr)
++{
++      return b->links[addr].next != NULL;
++}
++static inline unsigned
++efrm_buddy_free_list_first(struct efrm_buddy_allocator *b, unsigned order)
++{
++      return (unsigned)(b->free_lists[order].next - b->links);
++}
++
++int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order)
++{
++      unsigned o;
++      unsigned size = 1 << order;
++
++      DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __func__, order));
++      EFRM_ASSERT(b);
++      EFRM_ASSERT(order <= sizeof(unsigned) * 8 - 1);
++
++      b->order = order;
++      b->free_lists = vmalloc((order + 1) * sizeof(struct list_head));
++      if (b->free_lists == NULL)
++              goto fail1;
++
++      b->links = vmalloc(size * sizeof(struct list_head));
++      if (b->links == NULL)
++              goto fail2;
++
++      b->orders = vmalloc(size);
++      if (b->orders == NULL)
++              goto fail3;
++
++      memset(b->links, 0, size * sizeof(struct list_head));
++
++      for (o = 0; o <= b->order; ++o)
++              INIT_LIST_HEAD(b->free_lists + o);
++
++      efrm_buddy_free_list_add(b, b->order, 0);
++
++      return 0;
++
++fail3:
++      vfree(b->links);
++fail2:
++      vfree(b->free_lists);
++fail1:
++      return -ENOMEM;
++}
++
++void efrm_buddy_dtor(struct efrm_buddy_allocator *b)
++{
++      EFRM_ASSERT(b);
++
++      vfree(b->free_lists);
++      vfree(b->links);
++      vfree(b->orders);
++}
++
++int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order)
++{
++      unsigned smallest;
++      unsigned addr;
++
++      DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __func__, order));
++      EFRM_ASSERT(b);
++
++      /* Find smallest chunk that is big enough.  ?? Can optimise this by
++       ** keeping array of pointers to smallest chunk for each order.
++       */
++      smallest = order;
++      while (smallest <= b->order &&
++             efrm_buddy_free_list_empty(b, smallest))
++              ++smallest;
++
++      if (smallest > b->order) {
++              DEBUG_ALLOC(EFRM_NOTICE
++                          ("buddy - alloc order %d failed - max order %d",
++                           order, b->order););
++              return -ENOMEM;
++      }
++
++      /* Split blocks until we get one of the correct size. */
++      addr = efrm_buddy_free_list_pop(b, smallest);
++
++      DEBUG_ALLOC(EFRM_NOTICE("buddy - alloc %x order %d cut from order %d",
++                              addr, order, smallest););
++      while (smallest-- > order)
++              efrm_buddy_free_list_add(b, smallest, addr + (1 << smallest));
++
++      EFRM_DO_DEBUG(b->orders[addr] = (uint8_t) order);
++
++      EFRM_ASSERT(addr < 1u << b->order);
++      return addr;
++}
++
++void
++efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr,
++              unsigned order)
++{
++      unsigned buddy_addr;
++
++      DEBUG_ALLOC(EFRM_NOTICE("%s(%u, %u)", __func__, addr, order));
++      EFRM_ASSERT(b);
++      EFRM_ASSERT(order <= b->order);
++      EFRM_ASSERT((unsigned long)addr + ((unsigned long)1 << order) <=
++                  (unsigned long)1 << b->order);
++      EFRM_ASSERT(!efrm_buddy_addr_in_free_list(b, addr));
++      EFRM_ASSERT(b->orders[addr] == order);
++
++      /* merge free blocks */
++      while (order < b->order) {
++              buddy_addr = addr ^ (1 << order);
++              if (!efrm_buddy_addr_in_free_list(b, buddy_addr) ||
++                  b->orders[buddy_addr] != order)
++                      break;
++              efrm_buddy_free_list_del(b, buddy_addr);
++              if (buddy_addr < addr)
++                      addr = buddy_addr;
++              ++order;
++      }
++
++      DEBUG_ALLOC(EFRM_NOTICE
++                  ("buddy - free %x merged into order %d", addr, order););
++      efrm_buddy_free_list_add(b, order, addr);
++}
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/buffer_table.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/buffer_table.c        2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,209 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains abstraction of the buffer table on the NIC.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++/*
++** Might be worth keeping a bitmap of which entries are clear.  Then we
++** wouldn't need to clear them all again when we free an allocation.
++*/
++
++#include <ci/efrm/debug.h>
++#include <ci/driver/efab/hardware.h>
++#include <ci/efrm/nic_table.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/buddy.h>
++
++/*! Comment? */
++struct efrm_buffer_table {
++      spinlock_t lock;
++      struct efrm_buddy_allocator buddy;
++};
++
++/* Efab buffer state. */
++static struct efrm_buffer_table efrm_buffers;
++
++int efrm_buffer_table_ctor(unsigned low, unsigned high)
++{
++      int log2_n_entries, rc, i;
++
++      EFRM_ASSERT(high > 0);
++      EFRM_ASSERT(low < high);
++
++      EFRM_TRACE("%s: low=%u high=%u", __func__, low, high);
++      EFRM_NOTICE("%s: low=%u high=%u", __func__, low, high);
++
++      log2_n_entries = fls(high - 1);
++
++      rc = efrm_buddy_ctor(&efrm_buffers.buddy, log2_n_entries);
++      if (rc < 0) {
++              EFRM_ERR("efrm_buffer_table_ctor: efrm_buddy_ctor(%d) "
++                       "failed (%d)", log2_n_entries, rc);
++              return rc;
++      }
++      for (i = 0; i < (1 << log2_n_entries); ++i) {
++              rc = efrm_buddy_alloc(&efrm_buffers.buddy, 0);
++              EFRM_ASSERT(rc >= 0);
++              EFRM_ASSERT(rc < (1 << log2_n_entries));
++      }
++      for (i = low; i < (int) high; ++i)
++              efrm_buddy_free(&efrm_buffers.buddy, i, 0);
++
++      spin_lock_init(&efrm_buffers.lock);
++
++      EFRM_TRACE("%s: done", __func__);
++
++      return 0;
++}
++
++void efrm_buffer_table_dtor(void)
++{
++      /* ?? debug check that all allocations have been freed? */
++
++      spin_lock_destroy(&efrm_buffers.lock);
++      efrm_buddy_dtor(&efrm_buffers.buddy);
++
++      EFRM_TRACE("%s: done", __func__);
++}
++
++/**********************************************************************/
++
++int
++efrm_buffer_table_alloc(unsigned order,
++                      struct efhw_buffer_table_allocation *a)
++{
++      irq_flags_t lock_flags;
++      int rc;
++
++      EFRM_ASSERT(&efrm_buffers.buddy);
++      EFRM_ASSERT(a);
++
++      /* Round up to multiple of two, as the buffer clear logic works in
++       * pairs when not in "full" mode. */
++      order = max_t(unsigned, order, 1);
++
++      spin_lock_irqsave(&efrm_buffers.lock, lock_flags);
++      rc = efrm_buddy_alloc(&efrm_buffers.buddy, order);
++      spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags);
++
++      if (rc < 0) {
++              EFRM_ERR("efrm_buffer_table_alloc: failed (n=%ld) rc %d",
++                       1ul << order, rc);
++              return rc;
++      }
++
++      EFRM_TRACE("efrm_buffer_table_alloc: base=%d n=%ld",
++                 rc, 1ul << order);
++      a->order = order;
++      a->base = (unsigned)rc;
++      return 0;
++}
++
++void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a)
++{
++      irq_flags_t lock_flags;
++      struct efhw_nic *nic;
++      int nic_i;
++
++      EFRM_ASSERT(&efrm_buffers.buddy);
++      EFRM_ASSERT(a);
++      EFRM_ASSERT(a->base != -1);
++      EFRM_ASSERT((unsigned long)a->base + (1ul << a->order) <=
++                  efrm_buddy_size(&efrm_buffers.buddy));
++
++      EFRM_TRACE("efrm_buffer_table_free: base=%d n=%ld",
++                 a->base, (1ul << a->order));
++
++      EFRM_FOR_EACH_NIC(nic_i, nic)
++          efhw_nic_buffer_table_clear(nic, a->base, 1ul << a->order);
++
++      spin_lock_irqsave(&efrm_buffers.lock, lock_flags);
++      efrm_buddy_free(&efrm_buffers.buddy, a->base, a->order);
++      spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags);
++
++      EFRM_DO_DEBUG(a->base = a->order = -1);
++}
++
++/**********************************************************************/
++
++void
++efrm_buffer_table_set(struct efhw_buffer_table_allocation *a,
++                    struct efhw_nic *nic,
++                    unsigned i, dma_addr_t dma_addr, int owner)
++{
++      EFRM_ASSERT(a);
++      EFRM_ASSERT(i < (unsigned)1 << a->order);
++
++      efhw_nic_buffer_table_set(nic, dma_addr, EFHW_NIC_PAGE_SIZE,
++                                0, owner, a->base + i);
++}
++
++
++int efrm_buffer_table_size(void)
++{
++      return efrm_buddy_size(&efrm_buffers.buddy);
++}
++
++/**********************************************************************/
++
++int
++efrm_page_register(struct efhw_nic *nic, dma_addr_t dma_addr, int owner,
++                 efhw_buffer_addr_t *buf_addr_out)
++{
++      struct efhw_buffer_table_allocation alloc;
++      int rc;
++
++      rc = efrm_buffer_table_alloc(0, &alloc);
++      if (rc == 0) {
++              efrm_buffer_table_set(&alloc, nic, 0, dma_addr, owner);
++              efrm_buffer_table_commit();
++              *buf_addr_out = EFHW_BUFFER_ADDR(alloc.base, 0);
++      }
++      return rc;
++}
++EXPORT_SYMBOL(efrm_page_register);
++
++void efrm_page_unregister(efhw_buffer_addr_t buf_addr)
++{
++      struct efhw_buffer_table_allocation alloc;
++
++      alloc.order = 0;
++      alloc.base = EFHW_BUFFER_PAGE(buf_addr);
++      efrm_buffer_table_free(&alloc);
++}
++EXPORT_SYMBOL(efrm_page_unregister);
++
++void efrm_buffer_table_commit(void)
++{
++      struct efhw_nic *nic;
++      int nic_i;
++
++      EFRM_FOR_EACH_NIC(nic_i, nic)
++          efhw_nic_buffer_table_commit(nic);
++}
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h     2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,188 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC hardware interface.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_HARDWARE_H__
++#define __CI_DRIVER_EFAB_HARDWARE_H__
++
++#include "ci/driver/efab/hardware/workarounds.h"
++#include <ci/efhw/hardware_sysdep.h>
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Common EtherFabric definitions
++ *
++ *---------------------------------------------------------------------------*/
++
++#include <ci/efhw/debug.h>
++#include <ci/efhw/common.h>
++#include <ci/driver/efab/hardware/common.h>
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric varients
++ *
++ *---------------------------------------------------------------------------*/
++
++#include <ci/driver/efab/hardware/falcon.h>
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric Portable Hardware Layer defines
++ *
++ *---------------------------------------------------------------------------*/
++
++  /*-------------- Initialisation ------------ */
++#define efhw_nic_close_hardware(nic) \
++      ((nic)->efhw_func->close_hardware(nic))
++
++#define efhw_nic_init_hardware(nic, ev_handlers, mac_addr, non_irq_evq) \
++      ((nic)->efhw_func->init_hardware((nic), (ev_handlers), (mac_addr), \
++                                       (non_irq_evq)))
++
++/*-------------- Interrupt support  ------------ */
++/** Handle interrupt.  Return 0 if not handled, 1 if handled. */
++#define efhw_nic_interrupt(nic) \
++      ((nic)->efhw_func->interrupt(nic))
++
++#define efhw_nic_interrupt_enable(nic) \
++      ((nic)->efhw_func->interrupt_enable(nic))
++
++#define efhw_nic_interrupt_disable(nic) \
++      ((nic)->efhw_func->interrupt_disable(nic))
++
++#define efhw_nic_set_interrupt_moderation(nic, evq, val)                 \
++      ((nic)->efhw_func->set_interrupt_moderation(nic, evq, val))
++
++/*-------------- Event support  ------------ */
++
++#define efhw_nic_event_queue_enable(nic, evq, size, q_base, buf_base,   \
++                                  interrupting)                       \
++      ((nic)->efhw_func->event_queue_enable((nic), (evq), (size), (q_base), \
++                                            (buf_base), (interrupting)))
++
++#define efhw_nic_event_queue_disable(nic, evq, timer_only) \
++      ((nic)->efhw_func->event_queue_disable(nic, evq, timer_only))
++
++#define efhw_nic_wakeup_request(nic, q_base, index, evq) \
++      ((nic)->efhw_func->wakeup_request(nic, q_base, index, evq))
++
++#define efhw_nic_sw_event(nic, data, ev) \
++      ((nic)->efhw_func->sw_event(nic, data, ev))
++
++/*-------------- Filter support  ------------ */
++#define efhw_nic_ipfilter_set(nic, type, index, dmaq,         \
++                            saddr, sport, daddr, dport)       \
++      ((nic)->efhw_func->ipfilter_set(nic, type, index, dmaq, \
++                                      saddr, sport, daddr, dport))
++
++#define efhw_nic_ipfilter_clear(nic, index) \
++      ((nic)->efhw_func->ipfilter_clear(nic, index))
++
++/*-------------- DMA support  ------------ */
++#define efhw_nic_dmaq_tx_q_init(nic, dmaq, evq, owner, tag,           \
++                              dmaq_size, index, flags)                \
++      ((nic)->efhw_func->dmaq_tx_q_init(nic, dmaq, evq, owner, tag,   \
++                                        dmaq_size, index, flags))
++
++#define efhw_nic_dmaq_rx_q_init(nic, dmaq, evq, owner, tag,           \
++                              dmaq_size, index, flags) \
++      ((nic)->efhw_func->dmaq_rx_q_init(nic, dmaq, evq, owner, tag,   \
++                                        dmaq_size, index, flags))
++
++#define efhw_nic_dmaq_tx_q_disable(nic, dmaq) \
++      ((nic)->efhw_func->dmaq_tx_q_disable(nic, dmaq))
++
++#define efhw_nic_dmaq_rx_q_disable(nic, dmaq) \
++      ((nic)->efhw_func->dmaq_rx_q_disable(nic, dmaq))
++
++#define efhw_nic_flush_tx_dma_channel(nic, dmaq) \
++      ((nic)->efhw_func->flush_tx_dma_channel(nic, dmaq))
++
++#define efhw_nic_flush_rx_dma_channel(nic, dmaq) \
++      ((nic)->efhw_func->flush_rx_dma_channel(nic, dmaq))
++
++/*-------------- MAC Low level interface ---- */
++#define efhw_gmac_get_mac_addr(nic) \
++      ((nic)->gmac->get_mac_addr((nic)->gmac))
++
++/*-------------- Buffer table -------------- */
++#define efhw_nic_buffer_table_set(nic, addr, bufsz, region,           \
++                                own_id, buf_id)                       \
++      ((nic)->efhw_func->buffer_table_set(nic, addr, bufsz, region,   \
++                                          own_id, buf_id))
++
++#define efhw_nic_buffer_table_set_n(nic, buf_id, addr, bufsz,         \
++                                  region, n_pages, own_id) \
++      ((nic)->efhw_func->buffer_table_set_n(nic, buf_id, addr, bufsz, \
++                                            region, n_pages, own_id))
++
++#define efhw_nic_buffer_table_clear(nic, id, num) \
++      ((nic)->efhw_func->buffer_table_clear(nic, id, num))
++
++#define efhw_nic_buffer_table_commit(nic) \
++      ((nic)->efhw_func->buffer_table_commit(nic))
++
++/*-------------- New filter API ------------ */
++#define efhw_nic_filter_set(nic, spec, index_out) \
++      ((nic)->efhw_func->filter_set(nic, spec, index_out))
++
++#define efhw_nic_filter_clear(nic, type, index_out) \
++      ((nic)->efhw_func->filter_clear(nic, type, index_out))
++
++
++/* --- DMA --- */
++#define EFHW_DMA_ADDRMASK             (0xffffffffffffffffULL)
++
++/* --- Buffers --- */
++#define EFHW_BUFFER_ADDR              FALCON_BUFFER_4K_ADDR
++#define EFHW_BUFFER_PAGE              FALCON_BUFFER_4K_PAGE
++#define EFHW_BUFFER_OFF                       FALCON_BUFFER_4K_OFF
++
++/* --- Filters --- */
++#define EFHW_IP_FILTER_NUM            FALCON_FILTER_TBL_NUM
++
++#define EFHW_MAX_PAGE_SIZE            FALCON_MAX_PAGE_SIZE
++
++#if PAGE_SIZE <= EFHW_MAX_PAGE_SIZE
++#define EFHW_NIC_PAGE_SIZE PAGE_SIZE
++#else
++#define EFHW_NIC_PAGE_SIZE EFHW_MAX_PAGE_SIZE
++#endif
++#define EFHW_NIC_PAGE_MASK (~(EFHW_NIC_PAGE_SIZE-1))
++
++#endif /* __CI_DRIVER_EFAB_HARDWARE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,68 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC hardware interface common
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_HARDWARE_COMMON_H__
++#define __CI_DRIVER_EFAB_HARDWARE_COMMON_H__
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric constants
++ *
++ *---------------------------------------------------------------------------*/
++
++#define EFHW_1K               0x00000400u
++#define EFHW_2K               0x00000800u
++#define EFHW_4K               0x00001000u
++#define EFHW_8K               0x00002000u
++#define EFHW_16K      0x00004000u
++#define EFHW_32K      0x00008000u
++#define EFHW_64K      0x00010000u
++#define EFHW_128K     0x00020000u
++#define EFHW_256K     0x00040000u
++#define EFHW_512K     0x00080000u
++#define EFHW_1M               0x00100000u
++#define EFHW_2M               0x00200000u
++#define EFHW_4M               0x00400000u
++#define EFHW_8M               0x00800000u
++#define EFHW_16M      0x01000000u
++#define EFHW_32M      0x02000000u
++#define EFHW_48M      0x03000000u
++#define EFHW_64M      0x04000000u
++#define EFHW_128M     0x08000000u
++#define EFHW_256M     0x10000000u
++#define EFHW_512M     0x20000000u
++#define EFHW_1G       0x40000000u
++#define EFHW_2G               0x80000000u
++#define EFHW_4G               0x100000000ULL
++#define EFHW_8G               0x200000000ULL
++
++#endif /* __CI_DRIVER_EFAB_HARDWARE_COMMON_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,422 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) specific
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_HARDWARE_FALCON_H__
++#define __CI_DRIVER_EFAB_HARDWARE_FALCON_H__
++
++/*----------------------------------------------------------------------------
++ * Compile options
++ *---------------------------------------------------------------------------*/
++
++/* Falcon has an 8K maximum page size. */
++#define FALCON_MAX_PAGE_SIZE EFHW_8K
++
++/* include the register definitions */
++#include <ci/driver/efab/hardware/falcon/falcon_core.h>
++#include <ci/driver/efab/hardware/falcon/falcon_desc.h>
++#include <ci/driver/efab/hardware/falcon/falcon_event.h>
++#include <ci/driver/efab/hardware/falcon/falcon_intr_vec.h>
++
++#define FALCON_DMA_TX_DESC_BYTES      8
++#define FALCON_DMA_RX_PHYS_DESC_BYTES 8
++#define FALCON_DMA_RX_BUF_DESC_BYTES  4
++
++
++/* ---- efhw_event_t helpers --- */
++
++#ifndef EFHW_IS_LITTLE_ENDIAN
++#error This needs lots of cpu_to_le64s() in
++#endif
++
++/*!\ TODO look at whether there is an efficiency gain to be had by
++  treating the event codes to 32bit masks as is done for EF1
++
++  These masks apply to the full 64 bits of the event to extract the
++  event code - followed by the common event codes to expect
++ */
++#define __FALCON_OPEN_MASK(WIDTH)  ((((uint64_t)1) << (WIDTH)) - 1)
++#define FALCON_EVENT_CODE_MASK \
++      (__FALCON_OPEN_MASK(EV_CODE_WIDTH) << EV_CODE_LBN)
++#define FALCON_EVENT_EV_Q_ID_MASK \
++      (__FALCON_OPEN_MASK(DRIVER_EV_EVQ_ID_WIDTH) << DRIVER_EV_EVQ_ID_LBN)
++#define FALCON_EVENT_TX_FLUSH_Q_ID_MASK \
++      (__FALCON_OPEN_MASK(DRIVER_EV_TX_DESCQ_ID_WIDTH) << \
++       DRIVER_EV_TX_DESCQ_ID_LBN)
++#define FALCON_EVENT_RX_FLUSH_Q_ID_MASK \
++      (__FALCON_OPEN_MASK(DRIVER_EV_RX_DESCQ_ID_WIDTH) << \
++       DRIVER_EV_RX_DESCQ_ID_LBN)
++#define FALCON_EVENT_DRV_SUBCODE_MASK \
++      (__FALCON_OPEN_MASK(DRIVER_EV_SUB_CODE_WIDTH) << \
++       DRIVER_EV_SUB_CODE_LBN)
++
++#define FALCON_EVENT_FMT         "[ev:%x:%08x:%08x]"
++#define FALCON_EVENT_PRI_ARG(e) \
++      ((unsigned)(((e).u64 & FALCON_EVENT_CODE_MASK) >> EV_CODE_LBN)), \
++      ((unsigned)((e).u64 >> 32)), ((unsigned)((e).u64 & 0xFFFFFFFF))
++
++#define FALCON_EVENT_CODE(evp)                ((evp)->u64 & FALCON_EVENT_CODE_MASK)
++#define FALCON_EVENT_WAKE_EVQ_ID(evp) \
++      (((evp)->u64 & FALCON_EVENT_EV_Q_ID_MASK) >> DRIVER_EV_EVQ_ID_LBN)
++#define FALCON_EVENT_TX_FLUSH_Q_ID(evp) \
++      (((evp)->u64 & FALCON_EVENT_TX_FLUSH_Q_ID_MASK) >> \
++       DRIVER_EV_TX_DESCQ_ID_LBN)
++#define FALCON_EVENT_RX_FLUSH_Q_ID(evp) \
++      (((evp)->u64 & FALCON_EVENT_RX_FLUSH_Q_ID_MASK) >> \
++       DRIVER_EV_RX_DESCQ_ID_LBN)
++#define FALCON_EVENT_DRIVER_SUBCODE(evp) \
++      (((evp)->u64 & FALCON_EVENT_DRV_SUBCODE_MASK) >> \
++       DRIVER_EV_SUB_CODE_LBN)
++
++#define FALCON_EVENT_CODE_CHAR        ((uint64_t)DRIVER_EV_DECODE << EV_CODE_LBN)
++#define FALCON_EVENT_CODE_SW  ((uint64_t)DRV_GEN_EV_DECODE << EV_CODE_LBN)
++
++
++/* so this is the size in bytes of an awful lot of things */
++#define FALCON_REGISTER128          (16)
++
++/* we define some unique dummy values as a debug aid */
++#ifdef _WIN32
++#define FALCON_ATOMIC_BASE            0xdeadbeef00000000ui64
++#else
++#define FALCON_ATOMIC_BASE            0xdeadbeef00000000ULL
++#endif
++#define FALCON_ATOMIC_UPD_REG         (FALCON_ATOMIC_BASE | 0x1)
++#define FALCON_ATOMIC_PTR_TBL_REG     (FALCON_ATOMIC_BASE | 0x2)
++#define FALCON_ATOMIC_SRPM_UDP_EVQ_REG        (FALCON_ATOMIC_BASE | 0x3)
++#define FALCON_ATOMIC_RX_FLUSH_DESCQ  (FALCON_ATOMIC_BASE | 0x4)
++#define FALCON_ATOMIC_TX_FLUSH_DESCQ  (FALCON_ATOMIC_BASE | 0x5)
++#define FALCON_ATOMIC_INT_EN_REG      (FALCON_ATOMIC_BASE | 0x6)
++#define FALCON_ATOMIC_TIMER_CMD_REG   (FALCON_ATOMIC_BASE | 0x7)
++#define FALCON_ATOMIC_PACE_REG                (FALCON_ATOMIC_BASE | 0x8)
++#define FALCON_ATOMIC_INT_ACK_REG     (FALCON_ATOMIC_BASE | 0x9)
++/* XXX It crashed with odd value in FALCON_ATOMIC_INT_ADR_REG */
++#define FALCON_ATOMIC_INT_ADR_REG     (FALCON_ATOMIC_BASE | 0xa)
++
++/*----------------------------------------------------------------------------
++ *
++ * PCI control blocks for Falcon -
++ *          (P) primary is for NET
++ *          (S) secondary is for CHAR
++ *
++ *---------------------------------------------------------------------------*/
++
++#define FALCON_P_CTR_AP_BAR   2
++#define FALCON_S_CTR_AP_BAR   0
++#define FALCON_S_DEVID                0x6703
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Falcon constants
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Note: the following constants have moved to values in struct efhw_nic:
++ *   FALCON_EVQ_TBL_NUM  ->  nic->num_evqs
++ *   FALCON_DMAQ_NUM     ->  nic->num_dmaqs
++ *   FALCON_TIMERS_NUM   ->  nic->num_times
++ * These replacement constants are used as sanity checks in assertions in
++ * certain functions that don't have access to struct efhw_nic.
++ */
++#define FALCON_DMAQ_NUM_SANITY          (EFHW_4K)
++#define FALCON_EVQ_TBL_NUM_SANITY       (EFHW_4K)
++#define FALCON_TIMERS_NUM_SANITY        (EFHW_4K)
++
++/* This value is an upper limit on the total number of filter table
++ * entries.  The actual size of filter table is determined at runtime, as
++ * it can vary.
++ */
++#define FALCON_FILTER_TBL_NUM         (EFHW_8K)
++
++/* max number of buffers which can be pushed before commiting */
++#define FALCON_BUFFER_UPD_MAX         (128)
++
++/* We can tell falcon to write its RX buffers in 32 byte quantums,
++   and since we pad packets 2 bytes to the right we can't use
++   a full page (not unless we use jumbo mode for all queues)
++
++   NOTE: tests/nic/dma.c assumes that the value here is the real NIC
++   value, so we explicitly round it down to the nearest 32 bytes */
++
++/* #define FALCON_RX_USR_BUF_SIZE    round_down(4096-2,32) */
++#define FALCON_RX_USR_BUF_SIZE                4064
++
++#define FALCON_EVQ_RPTR_REG_P0                0x400
++
++/*----------------------------------------------------------------------------
++ *
++ * Falcon requires user-space descriptor pushes to be:
++ *    dword[0-2]; wiob(); dword[3]
++ *
++ * Driver register access must be locked against other threads from
++ * the same driver but can be in any order: i.e dword[0-3]; wiob()
++ *
++ * The following helpers ensure that valid dword orderings are exercised
++ *
++ *---------------------------------------------------------------------------*/
++
++/* A union to allow writting 64bit values as 32bit values, without
++ * hitting the compilers aliasing rules. We hope the compiler optimises
++ * away the copy's anyway */
++union __u64to32 {
++      uint64_t u64;
++      struct {
++#ifdef EFHW_IS_LITTLE_ENDIAN
++              uint32_t a;
++              uint32_t b;
++#else
++              uint32_t b;
++              uint32_t a;
++#endif
++      } s;
++};
++
++static inline void
++falcon_write_ddd_d(volatile char __iomem *kva,
++                 uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
++{
++      writel(d0, kva + 0);
++      writel(d1, kva + 4);
++      writel(d2, kva + 8);
++      mmiowb();
++      writel(d3, kva + 12);
++}
++
++static inline void falcon_write_q(volatile char __iomem *kva, uint64_t q)
++{
++      union __u64to32 u;
++      u.u64 = q;
++
++      writel(u.s.a, kva);
++      mmiowb();
++      writel(u.s.b, kva + 4);
++}
++
++static inline void falcon_read_q(volatile char __iomem *addr, uint64_t *q0)
++{
++      /* It is essential that we read dword0 first, so that
++       * the shadow register is updated with the latest value
++       * and we get a self consistent value.
++       */
++      union __u64to32 u;
++      u.s.a = readl(addr);
++      rmb();
++      u.s.b = readl(addr + 4);
++
++      *q0 = u.u64;
++}
++
++static inline void
++falcon_write_qq(volatile char __iomem *kva, uint64_t q0, uint64_t q1)
++{
++      writeq(q0, kva + 0);
++      falcon_write_q(kva + 8, q1);
++}
++
++static inline void
++falcon_read_qq(volatile char __iomem *addr, uint64_t *q0, uint64_t *q1)
++{
++      falcon_read_q(addr, q0);
++      *q1 = readq(addr + 8);
++}
++
++
++
++/*----------------------------------------------------------------------------
++ *
++ * Buffer virtual addresses (4K buffers)
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Form a buffer virtual address from buffer ID and offset.  If the offset
++** is larger than the buffer size, then the buffer indexed will be
++** calculated appropriately.  It is the responsibility of the caller to
++** ensure that they have valid buffers programmed at that address.
++*/
++#define FALCON_VADDR_8K_S     (13)
++#define FALCON_VADDR_4K_S     (12)
++#define FALCON_VADDR_M                0xfffff /* post shift mask  */
++
++#define FALCON_BUFFER_8K_ADDR(id, off)        (((id) << FALCON_VADDR_8K_S) + (off))
++#define FALCON_BUFFER_8K_PAGE(vaddr) \
++      (((vaddr) >> FALCON_VADDR_8K_S) & FALCON_VADDR_M)
++#define FALCON_BUFFER_8K_OFF(vaddr) \
++      ((vaddr) & __FALCON_MASK32(FALCON_VADDR_8K_S))
++
++#define FALCON_BUFFER_4K_ADDR(id, off)        (((id) << FALCON_VADDR_4K_S) + (off))
++#define FALCON_BUFFER_4K_PAGE(vaddr) \
++      (((vaddr) >> FALCON_VADDR_4K_S) & FALCON_VADDR_M)
++#define FALCON_BUFFER_4K_OFF(vaddr) \
++      ((vaddr) & __FALCON_MASK32(FALCON_VADDR_4K_S))
++
++/*----------------------------------------------------------------------------
++ *
++ * Timer helpers
++ *
++ *---------------------------------------------------------------------------*/
++
++static inline int falcon_timer_page_addr(uint idx)
++{
++
++      EFHW_ASSERT(TIMER_CMD_REG_KER_OFST ==
++                  (TIMER_CMD_REG_PAGE4_OFST - 4 * EFHW_8K));
++
++      EFHW_ASSERT(idx < FALCON_TIMERS_NUM_SANITY);
++
++      if (idx < 4)
++              return TIMER_CMD_REG_KER_OFST + (idx * EFHW_8K);
++      else if (idx < 1024)
++              return TIMER_CMD_REG_PAGE4_OFST + ((idx - 4) * EFHW_8K);
++      else
++              return TIMER_CMD_REG_PAGE123K_OFST + ((idx - 1024) * EFHW_8K);
++}
++
++#define FALCON_TIMER_PAGE_MASK                (EFHW_8K-1)
++
++static inline int falcon_timer_page_offset(uint idx)
++{
++      return falcon_timer_page_addr(idx) & FALCON_TIMER_PAGE_MASK;
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * DMA Queue helpers
++ *
++ *---------------------------------------------------------------------------*/
++
++/* iSCSI queue for A1; see bug 5427 for more details. */
++#define FALCON_A1_ISCSI_DMAQ 4
++
++/*! returns an address within a bar of the TX DMA doorbell */
++static inline uint falcon_tx_dma_page_addr(uint dmaq_idx)
++{
++      uint page;
++
++      EFHW_ASSERT((((TX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) ==
++                   (((TX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1)))));
++
++      EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM_SANITY);
++
++      if (dmaq_idx < 1024)
++              page = TX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K);
++      else
++              page =
++                  TX_DESC_UPD_REG_PAGE123K_OFST +
++                  ((dmaq_idx - 1024) * EFHW_8K);
++
++      return page;
++}
++
++/*! returns an address within a bar of the RX DMA doorbell */
++static inline uint falcon_rx_dma_page_addr(uint dmaq_idx)
++{
++      uint page;
++
++      EFHW_ASSERT((((RX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) ==
++                   ((RX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1))));
++
++      EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM_SANITY);
++
++      if (dmaq_idx < 1024)
++              page = RX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K);
++      else
++              page =
++                  RX_DESC_UPD_REG_PAGE123K_OFST +
++                  ((dmaq_idx - 1024) * EFHW_8K);
++
++      return page;
++}
++
++/*! "page"=NIC-dependent register set size */
++#define FALCON_DMA_PAGE_MASK  (EFHW_8K-1)
++
++/*! returns an address within a bar of the start of the "page"
++    containing the TX DMA doorbell */
++static inline int falcon_tx_dma_page_base(uint dma_idx)
++{
++      return falcon_tx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK;
++}
++
++/*! returns an address within a bar of the start of the "page"
++    containing the RX DMA doorbell */
++static inline int falcon_rx_dma_page_base(uint dma_idx)
++{
++      return falcon_rx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK;
++}
++
++/*! returns an offset within a "page" of the TX DMA doorbell */
++static inline int falcon_tx_dma_page_offset(uint dma_idx)
++{
++      return falcon_tx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK;
++}
++
++/*! returns an offset within a "page" of the RX DMA doorbell */
++static inline int falcon_rx_dma_page_offset(uint dma_idx)
++{
++      return falcon_rx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK;
++}
++
++/*----------------------------------------------------------------------------
++ *
++ * Events
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Falcon nails down the event queue mappings */
++#define FALCON_EVQ_KERNEL0   (0)      /* hardwired for net driver */
++#define FALCON_EVQ_CHAR      (4)      /* char driver's event queue      */
++
++/* reserved by the drivers */
++#define FALCON_EVQ_TBL_RESERVED          (8)
++
++/* default DMA-Q sizes */
++#define FALCON_DMA_Q_DEFAULT_TX_SIZE  512
++
++#define FALCON_DMA_Q_DEFAULT_RX_SIZE  512
++
++#define FALCON_DMA_Q_DEFAULT_MMAP \
++      (FALCON_DMA_Q_DEFAULT_TX_SIZE * (FALCON_DMA_TX_DESC_BYTES * 2))
++
++/*----------------------------------------------------------------------------
++ *
++ * DEBUG - Analyser trigger
++ *
++ *---------------------------------------------------------------------------*/
++
++static inline void
++falcon_deadbeef(volatile char __iomem *efhw_kva, unsigned what)
++{
++      writel(what, efhw_kva + 0x300);
++      mmiowb();
++}
++#endif /* __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ */
++/*! \cidoxg_end */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h  2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,1147 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) core register
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#define  FALCON_EXTENDED_P_BAR 1
++
++/*************---- Bus Interface Unit Registers C Header ----*************/
++#define IOM_IND_ADR_REG_OFST 0x0 /* IO-mapped indirect access address
++                                  register */
++  #define IOM_AUTO_ADR_INC_EN_LBN 16
++  #define IOM_AUTO_ADR_INC_EN_WIDTH 1
++  #define IOM_IND_ADR_LBN 0
++  #define IOM_IND_ADR_WIDTH 16
++#define IOM_IND_DAT_REG_OFST 0x4 /* IO-mapped indirect access data register */
++  #define IOM_IND_DAT_LBN 0
++  #define IOM_IND_DAT_WIDTH 32
++#define ADR_REGION_REG_KER_OFST 0x0 /* Address region register */
++#define ADR_REGION_REG_OFST 0x0 /* Address region register */
++  #define ADR_REGION3_LBN 96
++  #define ADR_REGION3_WIDTH 18
++  #define ADR_REGION2_LBN 64
++  #define ADR_REGION2_WIDTH 18
++  #define ADR_REGION1_LBN 32
++  #define ADR_REGION1_WIDTH 18
++  #define ADR_REGION0_LBN 0
++  #define ADR_REGION0_WIDTH 18
++#define INT_EN_REG_KER_OFST 0x10 /* Kernel driver Interrupt enable register */
++  #define KER_INT_CHAR_LBN 4
++  #define KER_INT_CHAR_WIDTH 1
++  #define KER_INT_KER_LBN 3
++  #define KER_INT_KER_WIDTH 1
++  #define ILL_ADR_ERR_INT_EN_KER_LBN 2
++  #define ILL_ADR_ERR_INT_EN_KER_WIDTH 1
++  #define SRM_PERR_INT_EN_KER_LBN 1
++  #define SRM_PERR_INT_EN_KER_WIDTH 1
++  #define DRV_INT_EN_KER_LBN 0
++  #define DRV_INT_EN_KER_WIDTH 1
++#define INT_EN_REG_CHAR_OFST 0x20 /* Char Driver interrupt enable register */
++  #define CHAR_INT_CHAR_LBN 4
++  #define CHAR_INT_CHAR_WIDTH 1
++  #define CHAR_INT_KER_LBN 3
++  #define CHAR_INT_KER_WIDTH 1
++  #define ILL_ADR_ERR_INT_EN_CHAR_LBN 2
++  #define ILL_ADR_ERR_INT_EN_CHAR_WIDTH 1
++  #define SRM_PERR_INT_EN_CHAR_LBN 1
++  #define SRM_PERR_INT_EN_CHAR_WIDTH 1
++  #define DRV_INT_EN_CHAR_LBN 0
++  #define DRV_INT_EN_CHAR_WIDTH 1
++#define INT_ADR_REG_KER_OFST 0x30 /* Interrupt host address for Kernel driver */
++  #define INT_ADR_KER_LBN 0
++  #define INT_ADR_KER_WIDTH 64
++  #define DRV_INT_KER_LBN 32
++  #define DRV_INT_KER_WIDTH 1
++  #define EV_FF_HALF_INT_KER_LBN 3
++  #define EV_FF_HALF_INT_KER_WIDTH 1
++  #define EV_FF_FULL_INT_KER_LBN 2
++  #define EV_FF_FULL_INT_KER_WIDTH 1
++  #define ILL_ADR_ERR_INT_KER_LBN 1
++  #define ILL_ADR_ERR_INT_KER_WIDTH 1
++  #define SRAM_PERR_INT_KER_LBN 0
++  #define SRAM_PERR_INT_KER_WIDTH 1
++#define INT_ADR_REG_CHAR_OFST 0x40 /* Interrupt host address for Char driver */
++  #define INT_ADR_CHAR_LBN 0
++  #define INT_ADR_CHAR_WIDTH 64
++  #define DRV_INT_CHAR_LBN 32
++  #define DRV_INT_CHAR_WIDTH 1
++  #define EV_FF_HALF_INT_CHAR_LBN 3
++  #define EV_FF_HALF_INT_CHAR_WIDTH 1
++  #define EV_FF_FULL_INT_CHAR_LBN 2
++  #define EV_FF_FULL_INT_CHAR_WIDTH 1
++  #define ILL_ADR_ERR_INT_CHAR_LBN 1
++  #define ILL_ADR_ERR_INT_CHAR_WIDTH 1
++  #define SRAM_PERR_INT_CHAR_LBN 0
++  #define SRAM_PERR_INT_CHAR_WIDTH 1
++#define INT_ISR0_B0_OFST 0x90 /* B0 only */
++#define INT_ISR1_B0_OFST 0xA0
++#define INT_ACK_REG_KER_A1_OFST 0x50 /* Kernel interrupt acknowledge register */
++  #define RESERVED_LBN 0
++  #define RESERVED_WIDTH 32
++#define INT_ACK_REG_CHAR_A1_OFST 0x60 /* CHAR interrupt acknowledge register */
++  #define RESERVED_LBN 0
++  #define RESERVED_WIDTH 32
++/*************---- Global CSR Registers C Header ----*************/
++#define NIC_STAT_REG_KER_OFST 0x200 /* ASIC strap status register */
++#define NIC_STAT_REG_OFST 0x200 /* ASIC strap status register */
++  #define ONCHIP_SRAM_LBN 16
++  #define ONCHIP_SRAM_WIDTH 0
++  #define STRAP_PINS_LBN 0
++  #define STRAP_PINS_WIDTH 3
++#define GPIO_CTL_REG_KER_OFST 0x210 /* GPIO control register */
++#define GPIO_CTL_REG_OFST 0x210 /* GPIO control register */
++  #define GPIO_OEN_LBN 24
++  #define GPIO_OEN_WIDTH 4
++  #define GPIO_OUT_LBN 16
++  #define GPIO_OUT_WIDTH 4
++  #define GPIO_IN_LBN 8
++  #define GPIO_IN_WIDTH 4
++  #define GPIO_PWRUP_VALUE_LBN 0
++  #define GPIO_PWRUP_VALUE_WIDTH 4
++#define GLB_CTL_REG_KER_OFST 0x220 /* Global control register */
++#define GLB_CTL_REG_OFST 0x220 /* Global control register */
++  #define SWRST_LBN 0
++  #define SWRST_WIDTH 1
++#define FATAL_INTR_REG_KER_OFST 0x230 /* Fatal interrupt register for Kernel */
++  #define PCI_BUSERR_INT_KER_EN_LBN 43
++  #define PCI_BUSERR_INT_KER_EN_WIDTH 1
++  #define SRAM_OOB_INT_KER_EN_LBN 42
++  #define SRAM_OOB_INT_KER_EN_WIDTH 1
++  #define BUFID_OOB_INT_KER_EN_LBN 41
++  #define BUFID_OOB_INT_KER_EN_WIDTH 1
++  #define MEM_PERR_INT_KER_EN_LBN 40
++  #define MEM_PERR_INT_KER_EN_WIDTH 1
++  #define RBUF_OWN_INT_KER_EN_LBN 39
++  #define RBUF_OWN_INT_KER_EN_WIDTH 1
++  #define TBUF_OWN_INT_KER_EN_LBN 38
++  #define TBUF_OWN_INT_KER_EN_WIDTH 1
++  #define RDESCQ_OWN_INT_KER_EN_LBN 37
++  #define RDESCQ_OWN_INT_KER_EN_WIDTH 1
++  #define TDESCQ_OWN_INT_KER_EN_LBN 36
++  #define TDESCQ_OWN_INT_KER_EN_WIDTH 1
++  #define EVQ_OWN_INT_KER_EN_LBN 35
++  #define EVQ_OWN_INT_KER_EN_WIDTH 1
++  #define EVFF_OFLO_INT_KER_EN_LBN 34
++  #define EVFF_OFLO_INT_KER_EN_WIDTH 1
++  #define ILL_ADR_INT_KER_EN_LBN 33
++  #define ILL_ADR_INT_KER_EN_WIDTH 1
++  #define SRM_PERR_INT_KER_EN_LBN 32
++  #define SRM_PERR_INT_KER_EN_WIDTH 1
++  #define PCI_BUSERR_INT_KER_LBN 11
++  #define PCI_BUSERR_INT_KER_WIDTH 1
++  #define SRAM_OOB_INT_KER_LBN 10
++  #define SRAM_OOB_INT_KER_WIDTH 1
++  #define BUFID_OOB_INT_KER_LBN 9
++  #define BUFID_OOB_INT_KER_WIDTH 1
++  #define MEM_PERR_INT_KER_LBN 8
++  #define MEM_PERR_INT_KER_WIDTH 1
++  #define RBUF_OWN_INT_KER_LBN 7
++  #define RBUF_OWN_INT_KER_WIDTH 1
++  #define TBUF_OWN_INT_KER_LBN 6
++  #define TBUF_OWN_INT_KER_WIDTH 1
++  #define RDESCQ_OWN_INT_KER_LBN 5
++  #define RDESCQ_OWN_INT_KER_WIDTH 1
++  #define TDESCQ_OWN_INT_KER_LBN 4
++  #define TDESCQ_OWN_INT_KER_WIDTH 1
++  #define EVQ_OWN_INT_KER_LBN 3
++  #define EVQ_OWN_INT_KER_WIDTH 1
++  #define EVFF_OFLO_INT_KER_LBN 2
++  #define EVFF_OFLO_INT_KER_WIDTH 1
++  #define ILL_ADR_INT_KER_LBN 1
++  #define ILL_ADR_INT_KER_WIDTH 1
++  #define SRM_PERR_INT_KER_LBN 0
++  #define SRM_PERR_INT_KER_WIDTH 1
++#define FATAL_INTR_REG_OFST 0x240 /* Fatal interrupt register for Char */
++  #define PCI_BUSERR_INT_CHAR_EN_LBN 43
++  #define PCI_BUSERR_INT_CHAR_EN_WIDTH 1
++  #define SRAM_OOB_INT_CHAR_EN_LBN 42
++  #define SRAM_OOB_INT_CHAR_EN_WIDTH 1
++  #define BUFID_OOB_INT_CHAR_EN_LBN 41
++  #define BUFID_OOB_INT_CHAR_EN_WIDTH 1
++  #define MEM_PERR_INT_CHAR_EN_LBN 40
++  #define MEM_PERR_INT_CHAR_EN_WIDTH 1
++  #define RBUF_OWN_INT_CHAR_EN_LBN 39
++  #define RBUF_OWN_INT_CHAR_EN_WIDTH 1
++  #define TBUF_OWN_INT_CHAR_EN_LBN 38
++  #define TBUF_OWN_INT_CHAR_EN_WIDTH 1
++  #define RDESCQ_OWN_INT_CHAR_EN_LBN 37
++  #define RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
++  #define TDESCQ_OWN_INT_CHAR_EN_LBN 36
++  #define TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
++  #define EVQ_OWN_INT_CHAR_EN_LBN 35
++  #define EVQ_OWN_INT_CHAR_EN_WIDTH 1
++  #define EVFF_OFLO_INT_CHAR_EN_LBN 34
++  #define EVFF_OFLO_INT_CHAR_EN_WIDTH 1
++  #define ILL_ADR_INT_CHAR_EN_LBN 33
++  #define ILL_ADR_INT_CHAR_EN_WIDTH 1
++  #define SRM_PERR_INT_CHAR_EN_LBN 32
++  #define SRM_PERR_INT_CHAR_EN_WIDTH 1
++  #define FATAL_INTR_REG_EN_BITS    0xffffffffffffffffULL
++  #define PCI_BUSERR_INT_CHAR_LBN 11
++  #define PCI_BUSERR_INT_CHAR_WIDTH 1
++  #define SRAM_OOB_INT_CHAR_LBN 10
++  #define SRAM_OOB_INT_CHAR_WIDTH 1
++  #define BUFID_OOB_INT_CHAR_LBN 9
++  #define BUFID_OOB_INT_CHAR_WIDTH 1
++  #define MEM_PERR_INT_CHAR_LBN 8
++  #define MEM_PERR_INT_CHAR_WIDTH 1
++  #define RBUF_OWN_INT_CHAR_LBN 7
++  #define RBUF_OWN_INT_CHAR_WIDTH 1
++  #define TBUF_OWN_INT_CHAR_LBN 6
++  #define TBUF_OWN_INT_CHAR_WIDTH 1
++  #define RDESCQ_OWN_INT_CHAR_LBN 5
++  #define RDESCQ_OWN_INT_CHAR_WIDTH 1
++  #define TDESCQ_OWN_INT_CHAR_LBN 4
++  #define TDESCQ_OWN_INT_CHAR_WIDTH 1
++  #define EVQ_OWN_INT_CHAR_LBN 3
++  #define EVQ_OWN_INT_CHAR_WIDTH 1
++  #define EVFF_OFLO_INT_CHAR_LBN 2
++  #define EVFF_OFLO_INT_CHAR_WIDTH 1
++  #define ILL_ADR_INT_CHAR_LBN 1
++  #define ILL_ADR_INT_CHAR_WIDTH 1
++  #define SRM_PERR_INT_CHAR_LBN 0
++  #define SRM_PERR_INT_CHAR_WIDTH 1
++#define DP_CTRL_REG_OFST 0x250 /* Datapath control register */
++  #define FLS_EVQ_ID_LBN 0
++  #define FLS_EVQ_ID_WIDTH 12
++#define MEM_STAT_REG_KER_OFST 0x260 /* Memory status register */
++#define MEM_STAT_REG_OFST 0x260 /* Memory status register */
++  #define MEM_PERR_VEC_LBN 53
++  #define MEM_PERR_VEC_WIDTH 38
++  #define MBIST_CORR_LBN 38
++  #define MBIST_CORR_WIDTH 15
++  #define MBIST_ERR_LBN 0
++  #define MBIST_ERR_WIDTH 38
++#define DEBUG_REG_KER_OFST 0x270 /* Debug register */
++#define DEBUG_REG_OFST 0x270 /* Debug register */
++  #define DEBUG_BLK_SEL2_LBN 47
++  #define DEBUG_BLK_SEL2_WIDTH 3
++  #define DEBUG_BLK_SEL1_LBN 44
++  #define DEBUG_BLK_SEL1_WIDTH 3
++  #define DEBUG_BLK_SEL0_LBN 41
++  #define DEBUG_BLK_SEL0_WIDTH 3
++  #define MISC_DEBUG_ADDR_LBN 36
++  #define MISC_DEBUG_ADDR_WIDTH 5
++  #define SERDES_DEBUG_ADDR_LBN 31
++  #define SERDES_DEBUG_ADDR_WIDTH 5
++  #define EM_DEBUG_ADDR_LBN 26
++  #define EM_DEBUG_ADDR_WIDTH 5
++  #define SR_DEBUG_ADDR_LBN 21
++  #define SR_DEBUG_ADDR_WIDTH 5
++  #define EV_DEBUG_ADDR_LBN 16
++  #define EV_DEBUG_ADDR_WIDTH 5
++  #define RX_DEBUG_ADDR_LBN 11
++  #define RX_DEBUG_ADDR_WIDTH 5
++  #define TX_DEBUG_ADDR_LBN 6
++  #define TX_DEBUG_ADDR_WIDTH 5
++  #define BIU_DEBUG_ADDR_LBN 1
++  #define BIU_DEBUG_ADDR_WIDTH 5
++  #define DEBUG_EN_LBN 0
++  #define DEBUG_EN_WIDTH 1
++#define DRIVER_REG0_KER_OFST 0x280 /* Driver scratch register 0 */
++#define DRIVER_REG0_OFST 0x280 /* Driver scratch register 0 */
++  #define DRIVER_DW0_LBN 0
++  #define DRIVER_DW0_WIDTH 32
++#define DRIVER_REG1_KER_OFST 0x290 /* Driver scratch register 1 */
++#define DRIVER_REG1_OFST 0x290 /* Driver scratch register 1 */
++  #define DRIVER_DW1_LBN 0
++  #define DRIVER_DW1_WIDTH 32
++#define DRIVER_REG2_KER_OFST 0x2A0 /* Driver scratch register 2 */
++#define DRIVER_REG2_OFST 0x2A0 /* Driver scratch register 2 */
++  #define DRIVER_DW2_LBN 0
++  #define DRIVER_DW2_WIDTH 32
++#define DRIVER_REG3_KER_OFST 0x2B0 /* Driver scratch register 3 */
++#define DRIVER_REG3_OFST 0x2B0 /* Driver scratch register 3 */
++  #define DRIVER_DW3_LBN 0
++  #define DRIVER_DW3_WIDTH 32
++#define DRIVER_REG4_KER_OFST 0x2C0 /* Driver scratch register 4 */
++#define DRIVER_REG4_OFST 0x2C0 /* Driver scratch register 4 */
++  #define DRIVER_DW4_LBN 0
++  #define DRIVER_DW4_WIDTH 32
++#define DRIVER_REG5_KER_OFST 0x2D0 /* Driver scratch register 5 */
++#define DRIVER_REG5_OFST 0x2D0 /* Driver scratch register 5 */
++  #define DRIVER_DW5_LBN 0
++  #define DRIVER_DW5_WIDTH 32
++#define DRIVER_REG6_KER_OFST 0x2E0 /* Driver scratch register 6 */
++#define DRIVER_REG6_OFST 0x2E0 /* Driver scratch register 6 */
++  #define DRIVER_DW6_LBN 0
++  #define DRIVER_DW6_WIDTH 32
++#define DRIVER_REG7_KER_OFST 0x2F0 /* Driver scratch register 7 */
++#define DRIVER_REG7_OFST 0x2F0 /* Driver scratch register 7 */
++  #define DRIVER_DW7_LBN 0
++  #define DRIVER_DW7_WIDTH 32
++#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */
++#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */
++  #define ALTERA_BUILD_VER_LBN 0
++  #define ALTERA_BUILD_VER_WIDTH 32
++
++/* so called CSR spare register
++    - contains separate parity enable bits for the various internal memory
++    blocks */
++#define MEM_PARITY_ERR_EN_REG_KER 0x310
++#define MEM_PARITY_ALL_BLOCKS_EN_LBN 64
++#define MEM_PARITY_ALL_BLOCKS_EN_WIDTH 38
++#define MEM_PARITY_TX_DATA_EN_LBN   72
++#define MEM_PARITY_TX_DATA_EN_WIDTH 2
++
++/*************---- Event & Timer Module Registers C Header ----*************/
++
++#if FALCON_EXTENDED_P_BAR
++#define EVQ_RPTR_REG_KER_OFST 0x11B00 /* Event queue read pointer register */
++#else
++#define EVQ_RPTR_REG_KER_OFST 0x1B00 /* Event queue read pointer register */
++#endif
++
++#define EVQ_RPTR_REG_OFST 0xFA0000 /* Event queue read pointer register
++                                    array. */
++  #define EVQ_RPTR_LBN 0
++  #define EVQ_RPTR_WIDTH 15
++
++#if FALCON_EXTENDED_P_BAR
++#define EVQ_PTR_TBL_KER_OFST 0x11A00 /* Event queue pointer table for kernel
++                                      access */
++#else
++#define EVQ_PTR_TBL_KER_OFST 0x1A00 /* Event queue pointer table for kernel
++                                     access */
++#endif
++
++#define EVQ_PTR_TBL_CHAR_OFST 0xF60000 /* Event queue pointer table for char
++                                        direct access */
++  #define EVQ_WKUP_OR_INT_EN_LBN 39
++  #define EVQ_WKUP_OR_INT_EN_WIDTH 1
++  #define EVQ_NXT_WPTR_LBN 24
++  #define EVQ_NXT_WPTR_WIDTH 15
++  #define EVQ_EN_LBN 23
++  #define EVQ_EN_WIDTH 1
++  #define EVQ_SIZE_LBN 20
++  #define EVQ_SIZE_WIDTH 3
++  #define EVQ_BUF_BASE_ID_LBN 0
++  #define EVQ_BUF_BASE_ID_WIDTH 20
++#define TIMER_CMD_REG_KER_OFST 0x420 /* Timer table for kernel access.
++                                      Page-mapped */
++#define TIMER_CMD_REG_PAGE4_OFST 0x8420 /* Timer table for user-level access.
++                                         Page-mapped. For lowest 1K queues.
++                                       */
++#define TIMER_CMD_REG_PAGE123K_OFST 0x1000420 /* Timer table for user-level
++                                               access. Page-mapped.
++                                               For upper 3K queues. */
++#define TIMER_TBL_OFST 0xF70000 /* Timer table for char driver direct access */
++  #define TIMER_MODE_LBN 12
++  #define TIMER_MODE_WIDTH 2
++  #define TIMER_VAL_LBN 0
++  #define TIMER_VAL_WIDTH 12
++  #define TIMER_MODE_INT_HLDOFF 2
++  #define EVQ_BUF_SIZE_LBN 0
++  #define EVQ_BUF_SIZE_WIDTH 1
++#define DRV_EV_REG_KER_OFST 0x440 /* Driver generated event register */
++#define DRV_EV_REG_OFST 0x440 /* Driver generated event register */
++  #define DRV_EV_QID_LBN 64
++  #define DRV_EV_QID_WIDTH 12
++  #define DRV_EV_DATA_LBN 0
++  #define DRV_EV_DATA_WIDTH 64
++#define EVQ_CTL_REG_KER_OFST 0x450 /* Event queue control register */
++#define EVQ_CTL_REG_OFST 0x450 /* Event queue control register */
++  #define RX_EVQ_WAKEUP_MASK_B0_LBN 15
++  #define RX_EVQ_WAKEUP_MASK_B0_WIDTH 6
++  #define EVQ_OWNERR_CTL_LBN 14
++  #define EVQ_OWNERR_CTL_WIDTH 1
++  #define EVQ_FIFO_AF_TH_LBN 8
++  #define EVQ_FIFO_AF_TH_WIDTH 6
++  #define EVQ_FIFO_NOTAF_TH_LBN 0
++  #define EVQ_FIFO_NOTAF_TH_WIDTH 6
++/*************---- SRAM Module Registers C Header ----*************/
++#define BUF_TBL_CFG_REG_KER_OFST 0x600 /* Buffer table configuration register */
++#define BUF_TBL_CFG_REG_OFST 0x600 /* Buffer table configuration register */
++  #define BUF_TBL_MODE_LBN 3
++  #define BUF_TBL_MODE_WIDTH 1
++#define SRM_RX_DC_CFG_REG_KER_OFST 0x610 /* SRAM receive descriptor cache
++                                          configuration register */
++#define SRM_RX_DC_CFG_REG_OFST 0x610 /* SRAM receive descriptor cache
++                                      configuration register */
++  #define SRM_RX_DC_BASE_ADR_LBN 0
++  #define SRM_RX_DC_BASE_ADR_WIDTH 21
++#define SRM_TX_DC_CFG_REG_KER_OFST 0x620 /* SRAM transmit descriptor cache
++                                          configuration register */
++#define SRM_TX_DC_CFG_REG_OFST 0x620 /* SRAM transmit descriptor cache
++                                      configuration register */
++  #define SRM_TX_DC_BASE_ADR_LBN 0
++  #define SRM_TX_DC_BASE_ADR_WIDTH 21
++#define SRM_CFG_REG_KER_OFST 0x630 /* SRAM configuration register */
++#define SRM_CFG_REG_OFST 0x630 /* SRAM configuration register */
++  #define SRAM_OOB_ADR_INTEN_LBN 5
++  #define SRAM_OOB_ADR_INTEN_WIDTH 1
++  #define SRAM_OOB_BUF_INTEN_LBN 4
++  #define SRAM_OOB_BUF_INTEN_WIDTH 1
++  #define SRAM_BT_INIT_EN_LBN 3
++  #define SRAM_BT_INIT_EN_WIDTH 1
++  #define SRM_NUM_BANK_LBN 2
++  #define SRM_NUM_BANK_WIDTH 1
++  #define SRM_BANK_SIZE_LBN 0
++  #define SRM_BANK_SIZE_WIDTH 2
++#define BUF_TBL_UPD_REG_KER_OFST 0x650 /* Buffer table update register */
++#define BUF_TBL_UPD_REG_OFST 0x650 /* Buffer table update register */
++  #define BUF_UPD_CMD_LBN 63
++  #define BUF_UPD_CMD_WIDTH 1
++  #define BUF_CLR_CMD_LBN 62
++  #define BUF_CLR_CMD_WIDTH 1
++  #define BUF_CLR_END_ID_LBN 32
++  #define BUF_CLR_END_ID_WIDTH 20
++  #define BUF_CLR_START_ID_LBN 0
++  #define BUF_CLR_START_ID_WIDTH 20
++#define SRM_UPD_EVQ_REG_KER_OFST 0x660 /* Buffer table update register */
++#define SRM_UPD_EVQ_REG_OFST 0x660 /* Buffer table update register */
++  #define SRM_UPD_EVQ_ID_LBN 0
++  #define SRM_UPD_EVQ_ID_WIDTH 12
++#define SRAM_PARITY_REG_KER_OFST 0x670 /* SRAM parity register. */
++#define SRAM_PARITY_REG_OFST 0x670 /* SRAM parity register. */
++  #define FORCE_SRAM_PERR_LBN 0
++  #define FORCE_SRAM_PERR_WIDTH 1
++
++#if FALCON_EXTENDED_P_BAR
++#define BUF_HALF_TBL_KER_OFST 0x18000 /* Buffer table in half buffer table
++                                       mode direct access by kernel driver */
++#else
++#define BUF_HALF_TBL_KER_OFST 0x8000 /* Buffer table in half buffer table
++                                      mode direct access by kernel driver */
++#endif
++
++
++#define BUF_HALF_TBL_OFST 0x800000 /* Buffer table in half buffer table mode
++                                    direct access by char driver */
++  #define BUF_ADR_HBUF_ODD_LBN 44
++  #define BUF_ADR_HBUF_ODD_WIDTH 20
++  #define BUF_OWNER_ID_HBUF_ODD_LBN 32
++  #define BUF_OWNER_ID_HBUF_ODD_WIDTH 12
++  #define BUF_ADR_HBUF_EVEN_LBN 12
++  #define BUF_ADR_HBUF_EVEN_WIDTH 20
++  #define BUF_OWNER_ID_HBUF_EVEN_LBN 0
++  #define BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
++
++
++#if FALCON_EXTENDED_P_BAR
++#define BUF_FULL_TBL_KER_OFST 0x18000 /* Buffer table in full buffer table
++                                       mode direct access by kernel driver */
++#else
++#define BUF_FULL_TBL_KER_OFST 0x8000 /* Buffer table in full buffer table mode
++                                      direct access by kernel driver */
++#endif
++
++
++
++
++#define BUF_FULL_TBL_OFST 0x800000 /* Buffer table in full buffer table mode
++                                    direct access by char driver */
++  #define IP_DAT_BUF_SIZE_LBN 50
++  #define IP_DAT_BUF_SIZE_WIDTH 1
++  #define BUF_ADR_REGION_LBN 48
++  #define BUF_ADR_REGION_WIDTH 2
++  #define BUF_ADR_FBUF_LBN 14
++  #define BUF_ADR_FBUF_WIDTH 34
++  #define BUF_OWNER_ID_FBUF_LBN 0
++  #define BUF_OWNER_ID_FBUF_WIDTH 14
++#define SRM_DBG_REG_OFST 0x3000000 /* SRAM debug access */
++  #define SRM_DBG_LBN 0
++  #define SRM_DBG_WIDTH 64
++/*************---- RX Datapath Registers C Header ----*************/
++
++#define RX_CFG_REG_KER_OFST 0x800 /* Receive configuration register */
++#define RX_CFG_REG_OFST 0x800 /* Receive configuration register */
++
++#if !defined(FALCON_64K_RXFIFO) && !defined(FALCON_PRE_02020029)
++# if !defined(FALCON_128K_RXFIFO)
++#  define FALCON_128K_RXFIFO
++# endif
++#endif
++
++#if defined(FALCON_128K_RXFIFO)
++
++/* new for B0 */
++  #define RX_TOEP_TCP_SUPPRESS_B0_LBN 48
++  #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++  #define RX_INGR_EN_B0_LBN 47
++  #define RX_INGR_EN_B0_WIDTH 1
++  #define RX_TOEP_IPV4_B0_LBN 46
++  #define RX_TOEP_IPV4_B0_WIDTH 1
++  #define RX_HASH_ALG_B0_LBN 45
++  #define RX_HASH_ALG_B0_WIDTH 1
++  #define RX_HASH_INSERT_HDR_B0_LBN 44
++  #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++  #define RX_DESC_PUSH_EN_B0_LBN 43
++  #define RX_DESC_PUSH_EN_B0_WIDTH 1
++  #define RX_RDW_PATCH_EN_LBN 42 /* Non head of line blocking */
++  #define RX_RDW_PATCH_EN_WIDTH 1
++  #define RX_PCI_BURST_SIZE_B0_LBN 39
++  #define RX_PCI_BURST_SIZE_B0_WIDTH 3
++  #define RX_OWNERR_CTL_B0_LBN 38
++  #define RX_OWNERR_CTL_B0_WIDTH 1
++  #define RX_XON_TX_TH_B0_LBN 33
++  #define RX_XON_TX_TH_B0_WIDTH 5
++  #define RX_XOFF_TX_TH_B0_LBN 28
++  #define RX_XOFF_TX_TH_B0_WIDTH 5
++  #define RX_USR_BUF_SIZE_B0_LBN 19
++  #define RX_USR_BUF_SIZE_B0_WIDTH 9
++  #define RX_XON_MAC_TH_B0_LBN 10
++  #define RX_XON_MAC_TH_B0_WIDTH 9
++  #define RX_XOFF_MAC_TH_B0_LBN 1
++  #define RX_XOFF_MAC_TH_B0_WIDTH 9
++  #define RX_XOFF_MAC_EN_B0_LBN 0
++  #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#elif !defined(FALCON_PRE_02020029)
++/* new for B0 */
++  #define RX_TOEP_TCP_SUPPRESS_B0_LBN 46
++  #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++  #define RX_INGR_EN_B0_LBN 45
++  #define RX_INGR_EN_B0_WIDTH 1
++  #define RX_TOEP_IPV4_B0_LBN 44
++  #define RX_TOEP_IPV4_B0_WIDTH 1
++  #define RX_HASH_ALG_B0_LBN 43
++  #define RX_HASH_ALG_B0_WIDTH 41
++  #define RX_HASH_INSERT_HDR_B0_LBN 42
++  #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++  #define RX_DESC_PUSH_EN_B0_LBN 41
++  #define RX_DESC_PUSH_EN_B0_WIDTH 1
++  #define RX_PCI_BURST_SIZE_B0_LBN 37
++  #define RX_PCI_BURST_SIZE_B0_WIDTH 3
++  #define RX_OWNERR_CTL_B0_LBN 36
++  #define RX_OWNERR_CTL_B0_WIDTH 1
++  #define RX_XON_TX_TH_B0_LBN 31
++  #define RX_XON_TX_TH_B0_WIDTH 5
++  #define RX_XOFF_TX_TH_B0_LBN 26
++  #define RX_XOFF_TX_TH_B0_WIDTH 5
++  #define RX_USR_BUF_SIZE_B0_LBN 17
++  #define RX_USR_BUF_SIZE_B0_WIDTH 9
++  #define RX_XON_MAC_TH_B0_LBN 9
++  #define RX_XON_MAC_TH_B0_WIDTH 8
++  #define RX_XOFF_MAC_TH_B0_LBN 1
++  #define RX_XOFF_MAC_TH_B0_WIDTH 8
++  #define RX_XOFF_MAC_EN_B0_LBN 0
++  #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#else
++/* new for B0 */
++  #define RX_TOEP_TCP_SUPPRESS_B0_LBN 44
++  #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1
++  #define RX_INGR_EN_B0_LBN 43
++  #define RX_INGR_EN_B0_WIDTH 1
++  #define RX_TOEP_IPV4_B0_LBN 42
++  #define RX_TOEP_IPV4_B0_WIDTH 1
++  #define RX_HASH_ALG_B0_LBN 41
++  #define RX_HASH_ALG_B0_WIDTH 41
++  #define RX_HASH_INSERT_HDR_B0_LBN 40
++  #define RX_HASH_INSERT_HDR_B0_WIDTH 1
++/* moved for B0 */
++  #define RX_DESC_PUSH_EN_B0_LBN 35
++  #define RX_DESC_PUSH_EN_B0_WIDTH 1
++  #define RX_PCI_BURST_SIZE_B0_LBN 35
++  #define RX_PCI_BURST_SIZE_B0_WIDTH 2
++  #define RX_OWNERR_CTL_B0_LBN 34
++  #define RX_OWNERR_CTL_B0_WIDTH 1
++  #define RX_XON_TX_TH_B0_LBN 29
++  #define RX_XON_TX_TH_B0_WIDTH 5
++  #define RX_XOFF_TX_TH_B0_LBN 24
++  #define RX_XOFF_TX_TH_B0_WIDTH 5
++  #define RX_USR_BUF_SIZE_B0_LBN 15
++  #define RX_USR_BUF_SIZE_B0_WIDTH 9
++  #define RX_XON_MAC_TH_B0_LBN 8
++  #define RX_XON_MAC_TH_B0_WIDTH 7
++  #define RX_XOFF_MAC_TH_B0_LBN 1
++  #define RX_XOFF_MAC_TH_B0_WIDTH 7
++  #define RX_XOFF_MAC_EN_B0_LBN 0
++  #define RX_XOFF_MAC_EN_B0_WIDTH 1
++
++#endif
++
++/* A0/A1 */
++  #define RX_PUSH_EN_A1_LBN 35
++  #define RX_PUSH_EN_A1_WIDTH 1
++  #define RX_PCI_BURST_SIZE_A1_LBN 31
++  #define RX_PCI_BURST_SIZE_A1_WIDTH 3
++  #define RX_OWNERR_CTL_A1_LBN 30
++  #define RX_OWNERR_CTL_A1_WIDTH 1
++  #define RX_XON_TX_TH_A1_LBN 25
++  #define RX_XON_TX_TH_A1_WIDTH 5
++  #define RX_XOFF_TX_TH_A1_LBN 20
++  #define RX_XOFF_TX_TH_A1_WIDTH 5
++  #define RX_USR_BUF_SIZE_A1_LBN 11
++  #define RX_USR_BUF_SIZE_A1_WIDTH 9
++  #define RX_XON_MAC_TH_A1_LBN 6
++  #define RX_XON_MAC_TH_A1_WIDTH 5
++  #define RX_XOFF_MAC_TH_A1_LBN 1
++  #define RX_XOFF_MAC_TH_A1_WIDTH 5
++  #define RX_XOFF_MAC_EN_A1_LBN 0
++  #define RX_XOFF_MAC_EN_A1_WIDTH 1
++
++#define RX_FILTER_CTL_REG_OFST 0x810 /* Receive filter control registers */
++  #define SCATTER_ENBL_NO_MATCH_Q_B0_LBN 40
++  #define SCATTER_ENBL_NO_MATCH_Q_B0_WIDTH 1
++  #define UDP_FULL_SRCH_LIMIT_LBN 32
++  #define UDP_FULL_SRCH_LIMIT_WIDTH 8
++  #define NUM_KER_LBN 24
++  #define NUM_KER_WIDTH 2
++  #define UDP_WILD_SRCH_LIMIT_LBN 16
++  #define UDP_WILD_SRCH_LIMIT_WIDTH 8
++  #define TCP_WILD_SRCH_LIMIT_LBN 8
++  #define TCP_WILD_SRCH_LIMIT_WIDTH 8
++  #define TCP_FULL_SRCH_LIMIT_LBN 0
++  #define TCP_FULL_SRCH_LIMIT_WIDTH 8
++#define RX_FLUSH_DESCQ_REG_KER_OFST 0x820 /* Receive flush descriptor queue
++                                           register */
++#define RX_FLUSH_DESCQ_REG_OFST 0x820 /* Receive flush descriptor queue
++                                       register */
++  #define RX_FLUSH_DESCQ_CMD_LBN 24
++  #define RX_FLUSH_DESCQ_CMD_WIDTH 1
++  #define RX_FLUSH_EVQ_ID_LBN 12
++  #define RX_FLUSH_EVQ_ID_WIDTH 12
++  #define RX_FLUSH_DESCQ_LBN 0
++  #define RX_FLUSH_DESCQ_WIDTH 12
++#define RX_DESC_UPD_REG_KER_OFST 0x830 /* Kernel  receive descriptor update
++                                        register. Page-mapped */
++#define RX_DESC_UPD_REG_PAGE4_OFST 0x8830 /* Char & user receive descriptor
++                                           update register. Page-mapped.
++                                           For lowest 1K queues. */
++#define RX_DESC_UPD_REG_PAGE123K_OFST 0x1000830 /* Char & user receive
++                                                 descriptor update register.
++                                                 Page-mapped. For upper
++                                                 3K queues. */
++  #define RX_DESC_WPTR_LBN 96
++  #define RX_DESC_WPTR_WIDTH 12
++  #define RX_DESC_PUSH_CMD_LBN 95
++  #define RX_DESC_PUSH_CMD_WIDTH 1
++  #define RX_DESC_LBN 0
++  #define RX_DESC_WIDTH 64
++  #define RX_KER_DESC_LBN 0
++  #define RX_KER_DESC_WIDTH 64
++  #define RX_USR_DESC_LBN 0
++  #define RX_USR_DESC_WIDTH 32
++#define RX_DC_CFG_REG_KER_OFST 0x840 /* Receive descriptor cache
++                                      configuration register */
++#define RX_DC_CFG_REG_OFST 0x840 /* Receive descriptor cache
++                                  configuration register */
++  #define RX_DC_SIZE_LBN 0
++  #define RX_DC_SIZE_WIDTH 2
++#define RX_DC_PF_WM_REG_KER_OFST 0x850 /* Receive descriptor cache pre-fetch
++                                        watermark register */
++#define RX_DC_PF_WM_REG_OFST 0x850 /* Receive descriptor cache pre-fetch
++                                    watermark register */
++  #define RX_DC_PF_LWM_LO_LBN 0
++  #define RX_DC_PF_LWM_LO_WIDTH 6
++
++#define RX_RSS_TKEY_B0_OFST 0x860 /* RSS Toeplitz hash key (B0 only) */
++
++#define RX_NODESC_DROP_REG 0x880
++  #define RX_NODESC_DROP_CNT_LBN 0
++  #define RX_NODESC_DROP_CNT_WIDTH 16
++
++#define XM_TX_CFG_REG_OFST 0x1230
++  #define XM_AUTO_PAD_LBN 5
++  #define XM_AUTO_PAD_WIDTH 1
++
++#define RX_FILTER_TBL0_OFST 0xF00000 /* Receive filter table - even entries */
++  #define RSS_EN_0_B0_LBN 110
++  #define RSS_EN_0_B0_WIDTH 1
++  #define SCATTER_EN_0_B0_LBN 109
++  #define SCATTER_EN_0_B0_WIDTH 1
++  #define TCP_UDP_0_LBN 108
++  #define TCP_UDP_0_WIDTH 1
++  #define RXQ_ID_0_LBN 96
++  #define RXQ_ID_0_WIDTH 12
++  #define DEST_IP_0_LBN 64
++  #define DEST_IP_0_WIDTH 32
++  #define DEST_PORT_TCP_0_LBN 48
++  #define DEST_PORT_TCP_0_WIDTH 16
++  #define SRC_IP_0_LBN 16
++  #define SRC_IP_0_WIDTH 32
++  #define SRC_TCP_DEST_UDP_0_LBN 0
++  #define SRC_TCP_DEST_UDP_0_WIDTH 16
++#define RX_FILTER_TBL1_OFST 0xF00010 /* Receive filter table - odd entries */
++  #define RSS_EN_1_B0_LBN 110
++  #define RSS_EN_1_B0_WIDTH 1
++  #define SCATTER_EN_1_B0_LBN 109
++  #define SCATTER_EN_1_B0_WIDTH 1
++  #define TCP_UDP_1_LBN 108
++  #define TCP_UDP_1_WIDTH 1
++  #define RXQ_ID_1_LBN 96
++  #define RXQ_ID_1_WIDTH 12
++  #define DEST_IP_1_LBN 64
++  #define DEST_IP_1_WIDTH 32
++  #define DEST_PORT_TCP_1_LBN 48
++  #define DEST_PORT_TCP_1_WIDTH 16
++  #define SRC_IP_1_LBN 16
++  #define SRC_IP_1_WIDTH 32
++  #define SRC_TCP_DEST_UDP_1_LBN 0
++  #define SRC_TCP_DEST_UDP_1_WIDTH 16
++
++#if FALCON_EXTENDED_P_BAR
++#define RX_DESC_PTR_TBL_KER_OFST 0x11800 /* Receive descriptor pointer
++                                          kernel access */
++#else
++#define RX_DESC_PTR_TBL_KER_OFST 0x1800 /* Receive descriptor pointer
++                                         kernel access */
++#endif
++
++
++#define RX_DESC_PTR_TBL_OFST 0xF40000 /* Receive descriptor pointer table */
++  #define RX_ISCSI_DDIG_EN_LBN 88
++  #define RX_ISCSI_DDIG_EN_WIDTH 1
++  #define RX_ISCSI_HDIG_EN_LBN 87
++  #define RX_ISCSI_HDIG_EN_WIDTH 1
++  #define RX_DESC_PREF_ACT_LBN 86
++  #define RX_DESC_PREF_ACT_WIDTH 1
++  #define RX_DC_HW_RPTR_LBN 80
++  #define RX_DC_HW_RPTR_WIDTH 6
++  #define RX_DESCQ_HW_RPTR_LBN 68
++  #define RX_DESCQ_HW_RPTR_WIDTH 12
++  #define RX_DESCQ_SW_WPTR_LBN 56
++  #define RX_DESCQ_SW_WPTR_WIDTH 12
++  #define RX_DESCQ_BUF_BASE_ID_LBN 36
++  #define RX_DESCQ_BUF_BASE_ID_WIDTH 20
++  #define RX_DESCQ_EVQ_ID_LBN 24
++  #define RX_DESCQ_EVQ_ID_WIDTH 12
++  #define RX_DESCQ_OWNER_ID_LBN 10
++  #define RX_DESCQ_OWNER_ID_WIDTH 14
++  #define RX_DESCQ_LABEL_LBN 5
++  #define RX_DESCQ_LABEL_WIDTH 5
++  #define RX_DESCQ_SIZE_LBN 3
++  #define RX_DESCQ_SIZE_WIDTH 2
++  #define RX_DESCQ_TYPE_LBN 2
++  #define RX_DESCQ_TYPE_WIDTH 1
++  #define RX_DESCQ_JUMBO_LBN 1
++  #define RX_DESCQ_JUMBO_WIDTH 1
++  #define RX_DESCQ_EN_LBN 0
++  #define RX_DESCQ_EN_WIDTH 1
++
++
++#define RX_RSS_INDIR_TBL_B0_OFST 0xFB0000 /* RSS indirection table (B0 only) */
++  #define RX_RSS_INDIR_ENT_B0_LBN 0
++  #define RX_RSS_INDIR_ENT_B0_WIDTH 6
++
++/*************---- TX Datapath Registers C Header ----*************/
++#define TX_FLUSH_DESCQ_REG_KER_OFST 0xA00 /* Transmit flush descriptor
++                                           queue register */
++#define TX_FLUSH_DESCQ_REG_OFST 0xA00 /* Transmit flush descriptor queue
++                                       register */
++  #define TX_FLUSH_DESCQ_CMD_LBN 12
++  #define TX_FLUSH_DESCQ_CMD_WIDTH 1
++  #define TX_FLUSH_DESCQ_LBN 0
++  #define TX_FLUSH_DESCQ_WIDTH 12
++#define TX_DESC_UPD_REG_KER_OFST 0xA10 /* Kernel transmit descriptor update
++                                        register. Page-mapped */
++#define TX_DESC_UPD_REG_PAGE4_OFST 0x8A10 /* Char & user transmit descriptor
++                                           update register. Page-mapped */
++#define TX_DESC_UPD_REG_PAGE123K_OFST 0x1000A10 /* Char & user transmit
++                                                 descriptor update register.
++                                                 Page-mapped */
++  #define TX_DESC_WPTR_LBN 96
++  #define TX_DESC_WPTR_WIDTH 12
++  #define TX_DESC_PUSH_CMD_LBN 95
++  #define TX_DESC_PUSH_CMD_WIDTH 1
++  #define TX_DESC_LBN 0
++  #define TX_DESC_WIDTH 95
++  #define TX_KER_DESC_LBN 0
++  #define TX_KER_DESC_WIDTH 64
++  #define TX_USR_DESC_LBN 0
++  #define TX_USR_DESC_WIDTH 64
++#define TX_DC_CFG_REG_KER_OFST 0xA20 /* Transmit descriptor cache
++                                      configuration register */
++#define TX_DC_CFG_REG_OFST 0xA20 /* Transmit descriptor cache configuration
++                                  register */
++  #define TX_DC_SIZE_LBN 0
++  #define TX_DC_SIZE_WIDTH 2
++
++#if FALCON_EXTENDED_P_BAR
++#define TX_DESC_PTR_TBL_KER_OFST 0x11900 /* Transmit descriptor pointer. */
++#else
++#define TX_DESC_PTR_TBL_KER_OFST 0x1900 /* Transmit descriptor pointer. */
++#endif
++
++
++#define TX_DESC_PTR_TBL_OFST 0xF50000 /* Transmit descriptor pointer */
++  #define TX_NON_IP_DROP_DIS_B0_LBN 91
++  #define TX_NON_IP_DROP_DIS_B0_WIDTH 1
++  #define TX_IP_CHKSM_DIS_B0_LBN 90
++  #define TX_IP_CHKSM_DIS_B0_WIDTH 1
++  #define TX_TCP_CHKSM_DIS_B0_LBN 89
++  #define TX_TCP_CHKSM_DIS_B0_WIDTH 1
++  #define TX_DESCQ_EN_LBN 88
++  #define TX_DESCQ_EN_WIDTH 1
++  #define TX_ISCSI_DDIG_EN_LBN 87
++  #define TX_ISCSI_DDIG_EN_WIDTH 1
++  #define TX_ISCSI_HDIG_EN_LBN 86
++  #define TX_ISCSI_HDIG_EN_WIDTH 1
++  #define TX_DC_HW_RPTR_LBN 80
++  #define TX_DC_HW_RPTR_WIDTH 6
++  #define TX_DESCQ_HW_RPTR_LBN 68
++  #define TX_DESCQ_HW_RPTR_WIDTH 12
++  #define TX_DESCQ_SW_WPTR_LBN 56
++  #define TX_DESCQ_SW_WPTR_WIDTH 12
++  #define TX_DESCQ_BUF_BASE_ID_LBN 36
++  #define TX_DESCQ_BUF_BASE_ID_WIDTH 20
++  #define TX_DESCQ_EVQ_ID_LBN 24
++  #define TX_DESCQ_EVQ_ID_WIDTH 12
++  #define TX_DESCQ_OWNER_ID_LBN 10
++  #define TX_DESCQ_OWNER_ID_WIDTH 14
++  #define TX_DESCQ_LABEL_LBN 5
++  #define TX_DESCQ_LABEL_WIDTH 5
++  #define TX_DESCQ_SIZE_LBN 3
++  #define TX_DESCQ_SIZE_WIDTH 2
++  #define TX_DESCQ_TYPE_LBN 1
++  #define TX_DESCQ_TYPE_WIDTH 2
++  #define TX_DESCQ_FLUSH_LBN 0
++  #define TX_DESCQ_FLUSH_WIDTH 1
++#define TX_CFG_REG_KER_OFST 0xA50 /* Transmit configuration register */
++#define TX_CFG_REG_OFST 0xA50 /* Transmit configuration register */
++  #define TX_IP_ID_P1_OFS_LBN 32
++  #define TX_IP_ID_P1_OFS_WIDTH 15
++  #define TX_IP_ID_P0_OFS_LBN 16
++  #define TX_IP_ID_P0_OFS_WIDTH 15
++  #define TX_TURBO_EN_LBN 3
++  #define TX_TURBO_EN_WIDTH 1
++  #define TX_OWNERR_CTL_LBN 2
++  #define TX_OWNERR_CTL_WIDTH 2
++  #define TX_NON_IP_DROP_DIS_LBN 1
++  #define TX_NON_IP_DROP_DIS_WIDTH 1
++  #define TX_IP_ID_REP_EN_LBN 0
++  #define TX_IP_ID_REP_EN_WIDTH 1
++#define TX_RESERVED_REG_KER_OFST 0xA80 /* Transmit configuration register */
++#define TX_RESERVED_REG_OFST 0xA80 /* Transmit configuration register */
++  #define TX_CSR_PUSH_EN_LBN 89
++  #define TX_CSR_PUSH_EN_WIDTH 1
++  #define TX_RX_SPACER_LBN 64
++  #define TX_RX_SPACER_WIDTH 8
++  #define TX_SW_EV_EN_LBN 59
++  #define TX_SW_EV_EN_WIDTH 1
++  #define TX_RX_SPACER_EN_LBN 57
++  #define TX_RX_SPACER_EN_WIDTH 1
++  #define TX_CSR_PREF_WD_TMR_LBN 24
++  #define TX_CSR_PREF_WD_TMR_WIDTH 16
++  #define TX_CSR_ONLY1TAG_LBN 21
++  #define TX_CSR_ONLY1TAG_WIDTH 1
++  #define TX_PREF_THRESHOLD_LBN 19
++  #define TX_PREF_THRESHOLD_WIDTH 2
++  #define TX_ONE_PKT_PER_Q_LBN 18
++  #define TX_ONE_PKT_PER_Q_WIDTH 1
++  #define TX_DIS_NON_IP_EV_LBN 17
++  #define TX_DIS_NON_IP_EV_WIDTH 1
++  #define TX_DMA_SPACER_LBN 8
++  #define TX_DMA_SPACER_WIDTH 8
++  #define TX_FLUSH_MIN_LEN_EN_B0_LBN 7
++  #define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1
++  #define TX_TCP_DIS_A1_LBN 7
++  #define TX_TCP_DIS_A1_WIDTH 1
++  #define TX_IP_DIS_A1_LBN 6
++  #define TX_IP_DIS_A1_WIDTH 1
++  #define TX_MAX_CPL_LBN 2
++  #define TX_MAX_CPL_WIDTH 2
++  #define TX_MAX_PREF_LBN 0
++  #define TX_MAX_PREF_WIDTH 2
++#define TX_VLAN_REG_OFST 0xAE0 /* Transmit VLAN tag register */
++  #define TX_VLAN_EN_LBN 127
++  #define TX_VLAN_EN_WIDTH 1
++  #define TX_VLAN7_PORT1_EN_LBN 125
++  #define TX_VLAN7_PORT1_EN_WIDTH 1
++  #define TX_VLAN7_PORT0_EN_LBN 124
++  #define TX_VLAN7_PORT0_EN_WIDTH 1
++  #define TX_VLAN7_LBN 112
++  #define TX_VLAN7_WIDTH 12
++  #define TX_VLAN6_PORT1_EN_LBN 109
++  #define TX_VLAN6_PORT1_EN_WIDTH 1
++  #define TX_VLAN6_PORT0_EN_LBN 108
++  #define TX_VLAN6_PORT0_EN_WIDTH 1
++  #define TX_VLAN6_LBN 96
++  #define TX_VLAN6_WIDTH 12
++  #define TX_VLAN5_PORT1_EN_LBN 93
++  #define TX_VLAN5_PORT1_EN_WIDTH 1
++  #define TX_VLAN5_PORT0_EN_LBN 92
++  #define TX_VLAN5_PORT0_EN_WIDTH 1
++  #define TX_VLAN5_LBN 80
++  #define TX_VLAN5_WIDTH 12
++  #define TX_VLAN4_PORT1_EN_LBN 77
++  #define TX_VLAN4_PORT1_EN_WIDTH 1
++  #define TX_VLAN4_PORT0_EN_LBN 76
++  #define TX_VLAN4_PORT0_EN_WIDTH 1
++  #define TX_VLAN4_LBN 64
++  #define TX_VLAN4_WIDTH 12
++  #define TX_VLAN3_PORT1_EN_LBN 61
++  #define TX_VLAN3_PORT1_EN_WIDTH 1
++  #define TX_VLAN3_PORT0_EN_LBN 60
++  #define TX_VLAN3_PORT0_EN_WIDTH 1
++  #define TX_VLAN3_LBN 48
++  #define TX_VLAN3_WIDTH 12
++  #define TX_VLAN2_PORT1_EN_LBN 45
++  #define TX_VLAN2_PORT1_EN_WIDTH 1
++  #define TX_VLAN2_PORT0_EN_LBN 44
++  #define TX_VLAN2_PORT0_EN_WIDTH 1
++  #define TX_VLAN2_LBN 32
++  #define TX_VLAN2_WIDTH 12
++  #define TX_VLAN1_PORT1_EN_LBN 29
++  #define TX_VLAN1_PORT1_EN_WIDTH 1
++  #define TX_VLAN1_PORT0_EN_LBN 28
++  #define TX_VLAN1_PORT0_EN_WIDTH 1
++  #define TX_VLAN1_LBN 16
++  #define TX_VLAN1_WIDTH 12
++  #define TX_VLAN0_PORT1_EN_LBN 13
++  #define TX_VLAN0_PORT1_EN_WIDTH 1
++  #define TX_VLAN0_PORT0_EN_LBN 12
++  #define TX_VLAN0_PORT0_EN_WIDTH 1
++  #define TX_VLAN0_LBN 0
++  #define TX_VLAN0_WIDTH 12
++#define TX_FIL_CTL_REG_OFST 0xAF0 /* Transmit filter control register */
++  #define TX_MADR1_FIL_EN_LBN 65
++  #define TX_MADR1_FIL_EN_WIDTH 1
++  #define TX_MADR0_FIL_EN_LBN 64
++  #define TX_MADR0_FIL_EN_WIDTH 1
++  #define TX_IPFIL31_PORT1_EN_LBN 63
++  #define TX_IPFIL31_PORT1_EN_WIDTH 1
++  #define TX_IPFIL31_PORT0_EN_LBN 62
++  #define TX_IPFIL31_PORT0_EN_WIDTH 1
++  #define TX_IPFIL30_PORT1_EN_LBN 61
++  #define TX_IPFIL30_PORT1_EN_WIDTH 1
++  #define TX_IPFIL30_PORT0_EN_LBN 60
++  #define TX_IPFIL30_PORT0_EN_WIDTH 1
++  #define TX_IPFIL29_PORT1_EN_LBN 59
++  #define TX_IPFIL29_PORT1_EN_WIDTH 1
++  #define TX_IPFIL29_PORT0_EN_LBN 58
++  #define TX_IPFIL29_PORT0_EN_WIDTH 1
++  #define TX_IPFIL28_PORT1_EN_LBN 57
++  #define TX_IPFIL28_PORT1_EN_WIDTH 1
++  #define TX_IPFIL28_PORT0_EN_LBN 56
++  #define TX_IPFIL28_PORT0_EN_WIDTH 1
++  #define TX_IPFIL27_PORT1_EN_LBN 55
++  #define TX_IPFIL27_PORT1_EN_WIDTH 1
++  #define TX_IPFIL27_PORT0_EN_LBN 54
++  #define TX_IPFIL27_PORT0_EN_WIDTH 1
++  #define TX_IPFIL26_PORT1_EN_LBN 53
++  #define TX_IPFIL26_PORT1_EN_WIDTH 1
++  #define TX_IPFIL26_PORT0_EN_LBN 52
++  #define TX_IPFIL26_PORT0_EN_WIDTH 1
++  #define TX_IPFIL25_PORT1_EN_LBN 51
++  #define TX_IPFIL25_PORT1_EN_WIDTH 1
++  #define TX_IPFIL25_PORT0_EN_LBN 50
++  #define TX_IPFIL25_PORT0_EN_WIDTH 1
++  #define TX_IPFIL24_PORT1_EN_LBN 49
++  #define TX_IPFIL24_PORT1_EN_WIDTH 1
++  #define TX_IPFIL24_PORT0_EN_LBN 48
++  #define TX_IPFIL24_PORT0_EN_WIDTH 1
++  #define TX_IPFIL23_PORT1_EN_LBN 47
++  #define TX_IPFIL23_PORT1_EN_WIDTH 1
++  #define TX_IPFIL23_PORT0_EN_LBN 46
++  #define TX_IPFIL23_PORT0_EN_WIDTH 1
++  #define TX_IPFIL22_PORT1_EN_LBN 45
++  #define TX_IPFIL22_PORT1_EN_WIDTH 1
++  #define TX_IPFIL22_PORT0_EN_LBN 44
++  #define TX_IPFIL22_PORT0_EN_WIDTH 1
++  #define TX_IPFIL21_PORT1_EN_LBN 43
++  #define TX_IPFIL21_PORT1_EN_WIDTH 1
++  #define TX_IPFIL21_PORT0_EN_LBN 42
++  #define TX_IPFIL21_PORT0_EN_WIDTH 1
++  #define TX_IPFIL20_PORT1_EN_LBN 41
++  #define TX_IPFIL20_PORT1_EN_WIDTH 1
++  #define TX_IPFIL20_PORT0_EN_LBN 40
++  #define TX_IPFIL20_PORT0_EN_WIDTH 1
++  #define TX_IPFIL19_PORT1_EN_LBN 39
++  #define TX_IPFIL19_PORT1_EN_WIDTH 1
++  #define TX_IPFIL19_PORT0_EN_LBN 38
++  #define TX_IPFIL19_PORT0_EN_WIDTH 1
++  #define TX_IPFIL18_PORT1_EN_LBN 37
++  #define TX_IPFIL18_PORT1_EN_WIDTH 1
++  #define TX_IPFIL18_PORT0_EN_LBN 36
++  #define TX_IPFIL18_PORT0_EN_WIDTH 1
++  #define TX_IPFIL17_PORT1_EN_LBN 35
++  #define TX_IPFIL17_PORT1_EN_WIDTH 1
++  #define TX_IPFIL17_PORT0_EN_LBN 34
++  #define TX_IPFIL17_PORT0_EN_WIDTH 1
++  #define TX_IPFIL16_PORT1_EN_LBN 33
++  #define TX_IPFIL16_PORT1_EN_WIDTH 1
++  #define TX_IPFIL16_PORT0_EN_LBN 32
++  #define TX_IPFIL16_PORT0_EN_WIDTH 1
++  #define TX_IPFIL15_PORT1_EN_LBN 31
++  #define TX_IPFIL15_PORT1_EN_WIDTH 1
++  #define TX_IPFIL15_PORT0_EN_LBN 30
++  #define TX_IPFIL15_PORT0_EN_WIDTH 1
++  #define TX_IPFIL14_PORT1_EN_LBN 29
++  #define TX_IPFIL14_PORT1_EN_WIDTH 1
++  #define TX_IPFIL14_PORT0_EN_LBN 28
++  #define TX_IPFIL14_PORT0_EN_WIDTH 1
++  #define TX_IPFIL13_PORT1_EN_LBN 27
++  #define TX_IPFIL13_PORT1_EN_WIDTH 1
++  #define TX_IPFIL13_PORT0_EN_LBN 26
++  #define TX_IPFIL13_PORT0_EN_WIDTH 1
++  #define TX_IPFIL12_PORT1_EN_LBN 25
++  #define TX_IPFIL12_PORT1_EN_WIDTH 1
++  #define TX_IPFIL12_PORT0_EN_LBN 24
++  #define TX_IPFIL12_PORT0_EN_WIDTH 1
++  #define TX_IPFIL11_PORT1_EN_LBN 23
++  #define TX_IPFIL11_PORT1_EN_WIDTH 1
++  #define TX_IPFIL11_PORT0_EN_LBN 22
++  #define TX_IPFIL11_PORT0_EN_WIDTH 1
++  #define TX_IPFIL10_PORT1_EN_LBN 21
++  #define TX_IPFIL10_PORT1_EN_WIDTH 1
++  #define TX_IPFIL10_PORT0_EN_LBN 20
++  #define TX_IPFIL10_PORT0_EN_WIDTH 1
++  #define TX_IPFIL9_PORT1_EN_LBN 19
++  #define TX_IPFIL9_PORT1_EN_WIDTH 1
++  #define TX_IPFIL9_PORT0_EN_LBN 18
++  #define TX_IPFIL9_PORT0_EN_WIDTH 1
++  #define TX_IPFIL8_PORT1_EN_LBN 17
++  #define TX_IPFIL8_PORT1_EN_WIDTH 1
++  #define TX_IPFIL8_PORT0_EN_LBN 16
++  #define TX_IPFIL8_PORT0_EN_WIDTH 1
++  #define TX_IPFIL7_PORT1_EN_LBN 15
++  #define TX_IPFIL7_PORT1_EN_WIDTH 1
++  #define TX_IPFIL7_PORT0_EN_LBN 14
++  #define TX_IPFIL7_PORT0_EN_WIDTH 1
++  #define TX_IPFIL6_PORT1_EN_LBN 13
++  #define TX_IPFIL6_PORT1_EN_WIDTH 1
++  #define TX_IPFIL6_PORT0_EN_LBN 12
++  #define TX_IPFIL6_PORT0_EN_WIDTH 1
++  #define TX_IPFIL5_PORT1_EN_LBN 11
++  #define TX_IPFIL5_PORT1_EN_WIDTH 1
++  #define TX_IPFIL5_PORT0_EN_LBN 10
++  #define TX_IPFIL5_PORT0_EN_WIDTH 1
++  #define TX_IPFIL4_PORT1_EN_LBN 9
++  #define TX_IPFIL4_PORT1_EN_WIDTH 1
++  #define TX_IPFIL4_PORT0_EN_LBN 8
++  #define TX_IPFIL4_PORT0_EN_WIDTH 1
++  #define TX_IPFIL3_PORT1_EN_LBN 7
++  #define TX_IPFIL3_PORT1_EN_WIDTH 1
++  #define TX_IPFIL3_PORT0_EN_LBN 6
++  #define TX_IPFIL3_PORT0_EN_WIDTH 1
++  #define TX_IPFIL2_PORT1_EN_LBN 5
++  #define TX_IPFIL2_PORT1_EN_WIDTH 1
++  #define TX_IPFIL2_PORT0_EN_LBN 4
++  #define TX_IPFIL2_PORT0_EN_WIDTH 1
++  #define TX_IPFIL1_PORT1_EN_LBN 3
++  #define TX_IPFIL1_PORT1_EN_WIDTH 1
++  #define TX_IPFIL1_PORT0_EN_LBN 2
++  #define TX_IPFIL1_PORT0_EN_WIDTH 1
++  #define TX_IPFIL0_PORT1_EN_LBN 1
++  #define TX_IPFIL0_PORT1_EN_WIDTH 1
++  #define TX_IPFIL0_PORT0_EN_LBN 0
++  #define TX_IPFIL0_PORT0_EN_WIDTH 1
++#define TX_IPFIL_TBL_OFST 0xB00 /* Transmit IP source address filter table */
++  #define TX_IPFIL_MASK_LBN 32
++  #define TX_IPFIL_MASK_WIDTH 32
++  #define TX_IP_SRC_ADR_LBN 0
++  #define TX_IP_SRC_ADR_WIDTH 32
++#define TX_PACE_REG_A1_OFST 0xF80000 /* Transmit pace control register */
++#define TX_PACE_REG_B0_OFST 0xA90    /* Transmit pace control register */
++  #define TX_PACE_SB_NOTAF_LBN 19
++  #define TX_PACE_SB_NOTAF_WIDTH 10
++  #define TX_PACE_SB_AF_LBN 9
++  #define TX_PACE_SB_AF_WIDTH 10
++  #define TX_PACE_FB_BASE_LBN 5
++  #define TX_PACE_FB_BASE_WIDTH 4
++  #define TX_PACE_BIN_TH_LBN 0
++  #define TX_PACE_BIN_TH_WIDTH 5
++#define TX_PACE_TBL_A1_OFST 0xF80040 /* Transmit pacing table */
++#define TX_PACE_TBL_FIRST_QUEUE_A1 4
++#define TX_PACE_TBL_B0_OFST 0xF80000 /* Transmit pacing table */
++#define TX_PACE_TBL_FIRST_QUEUE_B0 0
++  #define TX_PACE_LBN 0
++  #define TX_PACE_WIDTH 5
++
++/*************---- EE/Flash Registers C Header ----*************/
++#define EE_SPI_HCMD_REG_KER_OFST 0x100 /* SPI host command register */
++#define EE_SPI_HCMD_REG_OFST 0x100 /* SPI host command register */
++  #define EE_SPI_HCMD_CMD_EN_LBN 31
++  #define EE_SPI_HCMD_CMD_EN_WIDTH 1
++  #define EE_WR_TIMER_ACTIVE_LBN 28
++  #define EE_WR_TIMER_ACTIVE_WIDTH 1
++  #define EE_SPI_HCMD_SF_SEL_LBN 24
++  #define EE_SPI_HCMD_SF_SEL_WIDTH 1
++  #define EE_SPI_HCMD_DABCNT_LBN 16
++  #define EE_SPI_HCMD_DABCNT_WIDTH 5
++  #define EE_SPI_HCMD_READ_LBN 15
++  #define EE_SPI_HCMD_READ_WIDTH 1
++  #define EE_SPI_HCMD_DUBCNT_LBN 12
++  #define EE_SPI_HCMD_DUBCNT_WIDTH 2
++  #define EE_SPI_HCMD_ADBCNT_LBN 8
++  #define EE_SPI_HCMD_ADBCNT_WIDTH 2
++  #define EE_SPI_HCMD_ENC_LBN 0
++  #define EE_SPI_HCMD_ENC_WIDTH 8
++#define EE_SPI_HADR_REG_KER_OFST 0X110 /* SPI host address register */
++#define EE_SPI_HADR_REG_OFST 0X110 /* SPI host address register */
++  #define EE_SPI_HADR_DUBYTE_LBN 24
++  #define EE_SPI_HADR_DUBYTE_WIDTH 8
++  #define EE_SPI_HADR_ADR_LBN 0
++  #define EE_SPI_HADR_ADR_WIDTH 24
++#define EE_SPI_HDATA_REG_KER_OFST 0x120 /* SPI host data register */
++#define EE_SPI_HDATA_REG_OFST 0x120 /* SPI host data register */
++  #define EE_SPI_HDATA3_LBN 96
++  #define EE_SPI_HDATA3_WIDTH 32
++  #define EE_SPI_HDATA2_LBN 64
++  #define EE_SPI_HDATA2_WIDTH 32
++  #define EE_SPI_HDATA1_LBN 32
++  #define EE_SPI_HDATA1_WIDTH 32
++  #define EE_SPI_HDATA0_LBN 0
++  #define EE_SPI_HDATA0_WIDTH 32
++#define EE_BASE_PAGE_REG_KER_OFST 0x130 /* Expansion ROM base mirror register */
++#define EE_BASE_PAGE_REG_OFST 0x130 /* Expansion ROM base mirror register */
++  #define EE_EXP_ROM_WINDOW_BASE_LBN 16
++  #define EE_EXP_ROM_WINDOW_BASE_WIDTH 13
++  #define EE_EXPROM_MASK_LBN 0
++  #define EE_EXPROM_MASK_WIDTH 13
++#define EE_VPD_CFG0_REG_KER_OFST 0X140 /* SPI/VPD configuration register */
++#define EE_VPD_CFG0_REG_OFST 0X140 /* SPI/VPD configuration register */
++  #define EE_SF_FASTRD_EN_LBN 127
++  #define EE_SF_FASTRD_EN_WIDTH 1
++  #define EE_SF_CLOCK_DIV_LBN 120
++  #define EE_SF_CLOCK_DIV_WIDTH 7
++  #define EE_VPD_WIP_POLL_LBN 119
++  #define EE_VPD_WIP_POLL_WIDTH 1
++  #define EE_VPDW_LENGTH_LBN 80
++  #define EE_VPDW_LENGTH_WIDTH 15
++  #define EE_VPDW_BASE_LBN 64
++  #define EE_VPDW_BASE_WIDTH 15
++  #define EE_VPD_WR_CMD_EN_LBN 56
++  #define EE_VPD_WR_CMD_EN_WIDTH 8
++  #define EE_VPD_BASE_LBN 32
++  #define EE_VPD_BASE_WIDTH 24
++  #define EE_VPD_LENGTH_LBN 16
++  #define EE_VPD_LENGTH_WIDTH 13
++  #define EE_VPD_AD_SIZE_LBN 8
++  #define EE_VPD_AD_SIZE_WIDTH 5
++  #define EE_VPD_ACCESS_ON_LBN 5
++  #define EE_VPD_ACCESS_ON_WIDTH 1
++#define EE_VPD_SW_CNTL_REG_KER_OFST 0X150 /* VPD access SW control register */
++#define EE_VPD_SW_CNTL_REG_OFST 0X150 /* VPD access SW control register */
++  #define EE_VPD_CYCLE_PENDING_LBN 31
++  #define EE_VPD_CYCLE_PENDING_WIDTH 1
++  #define EE_VPD_CYC_WRITE_LBN 28
++  #define EE_VPD_CYC_WRITE_WIDTH 1
++  #define EE_VPD_CYC_ADR_LBN 0
++  #define EE_VPD_CYC_ADR_WIDTH 15
++#define EE_VPD_SW_DATA_REG_KER_OFST 0x160 /* VPD access SW data register */
++#define EE_VPD_SW_DATA_REG_OFST 0x160 /* VPD access SW data register */
++  #define EE_VPD_CYC_DAT_LBN 0
++  #define EE_VPD_CYC_DAT_WIDTH 32
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h  2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,75 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) descriptor
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++/*************---- Descriptors C Headers ----*************/
++/* Receive Kernel IP Descriptor */
++  #define RX_KER_BUF_SIZE_LBN 48
++  #define RX_KER_BUF_SIZE_WIDTH 14
++  #define RX_KER_BUF_REGION_LBN 46
++  #define RX_KER_BUF_REGION_WIDTH 2
++      #define RX_KER_BUF_REGION0_DECODE 0
++      #define RX_KER_BUF_REGION1_DECODE 1
++      #define RX_KER_BUF_REGION2_DECODE 2
++      #define RX_KER_BUF_REGION3_DECODE 3
++  #define RX_KER_BUF_ADR_LBN 0
++  #define RX_KER_BUF_ADR_WIDTH 46
++/* Receive User IP Descriptor */
++  #define RX_USR_2BYTE_OFS_LBN 20
++  #define RX_USR_2BYTE_OFS_WIDTH 12
++  #define RX_USR_BUF_ID_LBN 0
++  #define RX_USR_BUF_ID_WIDTH 20
++/* Transmit Kernel IP Descriptor */
++  #define TX_KER_PORT_LBN 63
++  #define TX_KER_PORT_WIDTH 1
++  #define TX_KER_CONT_LBN 62
++  #define TX_KER_CONT_WIDTH 1
++  #define TX_KER_BYTE_CNT_LBN 48
++  #define TX_KER_BYTE_CNT_WIDTH 14
++  #define TX_KER_BUF_REGION_LBN 46
++  #define TX_KER_BUF_REGION_WIDTH 2
++      #define TX_KER_BUF_REGION0_DECODE 0
++      #define TX_KER_BUF_REGION1_DECODE 1
++      #define TX_KER_BUF_REGION2_DECODE 2
++      #define TX_KER_BUF_REGION3_DECODE 3
++  #define TX_KER_BUF_ADR_LBN 0
++  #define TX_KER_BUF_ADR_WIDTH 46
++/* Transmit User IP Descriptor */
++  #define TX_USR_PORT_LBN 47
++  #define TX_USR_PORT_WIDTH 1
++  #define TX_USR_CONT_LBN 46
++  #define TX_USR_CONT_WIDTH 1
++  #define TX_USR_BYTE_CNT_LBN 33
++  #define TX_USR_BYTE_CNT_WIDTH 13
++  #define TX_USR_BUF_ID_LBN 13
++  #define TX_USR_BUF_ID_WIDTH 20
++  #define TX_USR_BYTE_OFS_LBN 0
++  #define TX_USR_BYTE_OFS_WIDTH 13
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,155 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) event
++ * definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++/*************---- Events Format C Header ----*************/
++/*************---- Event entry ----*************/
++  #define EV_CODE_LBN 60
++  #define EV_CODE_WIDTH 4
++      #define RX_IP_EV_DECODE 0
++      #define TX_IP_EV_DECODE 2
++      #define DRIVER_EV_DECODE 5
++      #define GLOBAL_EV_DECODE 6
++      #define DRV_GEN_EV_DECODE 7
++  #define EV_DATA_LBN 0
++  #define EV_DATA_WIDTH 60
++/******---- Receive IP events for both Kernel & User event queues ----******/
++  #define RX_EV_PKT_OK_LBN 56
++  #define RX_EV_PKT_OK_WIDTH 1
++  #define RX_EV_BUF_OWNER_ID_ERR_LBN 54
++  #define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++  #define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
++  #define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
++  #define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
++  #define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
++  #define RX_EV_ETH_CRC_ERR_LBN 50
++  #define RX_EV_ETH_CRC_ERR_WIDTH 1
++  #define RX_EV_FRM_TRUNC_LBN 49
++  #define RX_EV_FRM_TRUNC_WIDTH 1
++  #define RX_EV_DRIB_NIB_LBN 48
++  #define RX_EV_DRIB_NIB_WIDTH 1
++  #define RX_EV_TOBE_DISC_LBN 47
++  #define RX_EV_TOBE_DISC_WIDTH 1
++  #define RX_EV_PKT_TYPE_LBN 44
++  #define RX_EV_PKT_TYPE_WIDTH 3
++      #define RX_EV_PKT_TYPE_ETH_DECODE 0
++      #define RX_EV_PKT_TYPE_LLC_DECODE 1
++      #define RX_EV_PKT_TYPE_JUMBO_DECODE 2
++      #define RX_EV_PKT_TYPE_VLAN_DECODE 3
++      #define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4
++      #define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5
++  #define RX_EV_HDR_TYPE_LBN 42
++  #define RX_EV_HDR_TYPE_WIDTH 2
++      #define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0
++      #define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1
++      #define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2
++      #define RX_EV_HDR_TYPE_NON_IP_DECODE 3
++  #define RX_EV_DESC_Q_EMPTY_LBN 41
++  #define RX_EV_DESC_Q_EMPTY_WIDTH 1
++  #define RX_EV_MCAST_HASH_MATCH_LBN 40
++  #define RX_EV_MCAST_HASH_MATCH_WIDTH 1
++  #define RX_EV_MCAST_PKT_LBN 39
++  #define RX_EV_MCAST_PKT_WIDTH 1
++  #define RX_EV_Q_LABEL_LBN 32
++  #define RX_EV_Q_LABEL_WIDTH 5
++  #define RX_JUMBO_CONT_LBN 31
++  #define RX_JUMBO_CONT_WIDTH 1
++  #define RX_SOP_LBN 15
++  #define RX_SOP_WIDTH 1
++  #define RX_PORT_LBN 30
++  #define RX_PORT_WIDTH 1
++  #define RX_EV_BYTE_CNT_LBN 16
++  #define RX_EV_BYTE_CNT_WIDTH 14
++  #define RX_iSCSI_PKT_OK_LBN 14
++  #define RX_iSCSI_PKT_OK_WIDTH 1
++  #define RX_ISCSI_DDIG_ERR_LBN 13
++  #define RX_ISCSI_DDIG_ERR_WIDTH 1
++  #define RX_ISCSI_HDIG_ERR_LBN 12
++  #define RX_ISCSI_HDIG_ERR_WIDTH 1
++  #define RX_EV_DESC_PTR_LBN 0
++  #define RX_EV_DESC_PTR_WIDTH 12
++/******---- Transmit IP events for both Kernel & User event queues ----******/
++  #define TX_EV_PKT_ERR_LBN 38
++  #define TX_EV_PKT_ERR_WIDTH 1
++  #define TX_EV_PKT_TOO_BIG_LBN 37
++  #define TX_EV_PKT_TOO_BIG_WIDTH 1
++  #define TX_EV_Q_LABEL_LBN 32
++  #define TX_EV_Q_LABEL_WIDTH 5
++  #define TX_EV_PORT_LBN 16
++  #define TX_EV_PORT_WIDTH 1
++  #define TX_EV_WQ_FF_FULL_LBN 15
++  #define TX_EV_WQ_FF_FULL_WIDTH 1
++  #define TX_EV_BUF_OWNER_ID_ERR_LBN 14
++  #define TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
++  #define TX_EV_COMP_LBN 12
++  #define TX_EV_COMP_WIDTH 1
++  #define TX_EV_DESC_PTR_LBN 0
++  #define TX_EV_DESC_PTR_WIDTH 12
++/*************---- Char or Kernel driver events ----*************/
++  #define DRIVER_EV_SUB_CODE_LBN 56
++  #define DRIVER_EV_SUB_CODE_WIDTH 4
++      #define TX_DESCQ_FLS_DONE_EV_DECODE 0x0
++      #define RX_DESCQ_FLS_DONE_EV_DECODE 0x1
++      #define EVQ_INIT_DONE_EV_DECODE 0x2
++      #define EVQ_NOT_EN_EV_DECODE 0x3
++      #define RX_DESCQ_FLSFF_OVFL_EV_DECODE 0x4
++      #define SRM_UPD_DONE_EV_DECODE 0x5
++      #define WAKE_UP_EV_DECODE 0x6
++      #define TX_PKT_NON_TCP_UDP_DECODE 0x9
++      #define TIMER_EV_DECODE 0xA
++      #define RX_DSC_ERROR_EV_DECODE 0xE
++  #define DRIVER_EV_TX_DESCQ_ID_LBN 0
++  #define DRIVER_EV_TX_DESCQ_ID_WIDTH 12
++  #define DRIVER_EV_RX_DESCQ_ID_LBN 0
++  #define DRIVER_EV_RX_DESCQ_ID_WIDTH 12
++  #define DRIVER_EV_EVQ_ID_LBN 0
++  #define DRIVER_EV_EVQ_ID_WIDTH 12
++  #define DRIVER_TMR_ID_LBN 0
++  #define DRIVER_TMR_ID_WIDTH 12
++  #define DRIVER_EV_SRM_UPD_LBN 0
++  #define DRIVER_EV_SRM_UPD_WIDTH 2
++      #define SRM_CLR_EV_DECODE 0
++      #define SRM_UPD_EV_DECODE 1
++      #define SRM_ILLCLR_EV_DECODE 2
++/********---- Global events. Sent to both event queue 0 and 4. ----********/
++  #define XFP_PHY_INTR_LBN 10
++  #define XFP_PHY_INTR_WIDTH 1
++  #define XG_PHY_INTR_LBN 9
++  #define XG_PHY_INTR_WIDTH 1
++  #define G_PHY1_INTR_LBN 8
++  #define G_PHY1_INTR_WIDTH 1
++  #define G_PHY0_INTR_LBN 7
++  #define G_PHY0_INTR_WIDTH 1
++/*************---- Driver generated events ----*************/
++  #define DRV_GEN_EV_CODE_LBN 60
++  #define DRV_GEN_EV_CODE_WIDTH 4
++  #define DRV_GEN_EV_DATA_LBN 0
++  #define DRV_GEN_EV_DATA_WIDTH 60
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,44 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) interrupt
++ * vector definitions.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++/*************---- Interrupt Vector Format C Header ----*************/
++#define DW0_OFST 0x0 /* Double-word 0: Event queue FIFO interrupts */
++  #define EVQ_FIFO_HF_LBN 1
++  #define EVQ_FIFO_HF_WIDTH 1
++  #define EVQ_FIFO_AF_LBN 0
++  #define EVQ_FIFO_AF_WIDTH 1
++#define DW1_OFST 0x4 /* Double-word 1: Interrupt indicator */
++  #define INT_FLAG_LBN 0
++  #define INT_FLAG_WIDTH 1
++#define DW2_OFST 0x8 /* Double-word 2: Fatal interrupts */
++  #define FATAL_INT_LBN 0
++  #define FATAL_INT_WIDTH 1
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,67 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides workaround settings for EtherFabric NICs.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_WORKAROUNDS_H__
++#define __CI_DRIVER_EFAB_WORKAROUNDS_H__
++
++/*----------------------------------------------------------------------------
++ *
++ * Hardware workarounds which have global scope
++ *
++ *---------------------------------------------------------------------------*/
++
++#if defined(__CI_HARDWARE_CONFIG_FALCON_B0__)
++/*------------------------------- B0 ---------------------------------------*/
++
++#define BUG2175_WORKAROUND 0  /* TX event batching for dual port operation.
++                                 This removes the effect (dup TX events)
++                                 of the fix
++                                 (TX event per packet + batch events) */
++#define BUG5302_WORKAROUND 0  /* unstick TX DMAQ after out-of-range wr ptr */
++#define BUG5762_WORKAROUND 0  /* Set all queues to jumbo mode */
++#define BUG5391_WORKAROUND 0  /* Misaligned TX can't span 512-byte boundary */
++#define BUG7916_WORKAROUND 0  /* RX flush gets lost */
++
++#else
++/*------------------------------- A0/A1 ------------------------------------*/
++
++#define BUG2175_WORKAROUND 1  /* TX event batching for dual port operation.
++                                 This removes the effect (dup TX events)
++                                 of the fix
++                                 (TX event per packet + batch events) */
++#define BUG5302_WORKAROUND 1  /* unstick TX DMAQ after out-of-range wr ptr */
++#define BUG5762_WORKAROUND 1  /* Set all queues to jumbo mode */
++#define BUG5391_WORKAROUND 1  /* Misaligned TX can't span 512-byte boundary */
++#define BUG7916_WORKAROUND 1  /* RX flush gets lost */
++
++#endif /* B0/A01 */
++
++#endif /* __CI_DRIVER_EFAB_WORKAROUNDS_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h   2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,273 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains public EFX VI API to Solarflare resource manager.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_EFX_VI_H__
++#define __CI_DRIVER_RESOURCE_EFX_VI_H__
++
++/* Default size of event queue in the efx_vi resource.  Copied from
++ * CI_CFG_NETIF_EVENTQ_SIZE */
++#define EFX_VI_EVENTQ_SIZE_DEFAULT 1024
++
++extern int efx_vi_eventq_size;
++
++/**************************************************************************
++ * efx_vi_state types, allocation and free
++ **************************************************************************/
++
++/*! Handle for refering to a efx_vi */
++struct efx_vi_state;
++
++/*!
++ * Allocate an efx_vi, including event queue and pt_endpoint
++ *
++ * \param vih_out Pointer to a handle that is set on success
++ * \param ifindex Index of the network interface desired
++ * \return Zero on success (and vih_out set), non-zero on failure.
++ */
++extern int
++efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex);
++
++/*!
++ * Free a previously allocated efx_vi
++ *
++ * \param vih The handle of the efx_vi to free
++ */
++extern void
++efx_vi_free(struct efx_vi_state *vih);
++
++/*!
++ * Reset a previously allocated efx_vi
++ *
++ * \param vih The handle of the efx_vi to reset
++ */
++extern void
++efx_vi_reset(struct efx_vi_state *vih);
++
++/**************************************************************************
++ * efx_vi_eventq types and functions
++ **************************************************************************/
++
++/*!
++ * Register a function to receive callbacks when event queue timeouts
++ * or wakeups occur.  Only one function per efx_vi can be registered
++ * at once.
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param callback The function to callback
++ * \param context An argument to pass to the callback function
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_eventq_register_callback(struct efx_vi_state *vih,
++                              void (*callback)(void *context, int is_timeout),
++                              void *context);
++
++/*!
++ * Remove the current eventq timeout or wakeup callback function
++ *
++ * \param vih The handle to identify the efx_vi
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_eventq_kill_callback(struct efx_vi_state *vih);
++
++/**************************************************************************
++ * efx_vi_dma_map types and functions
++ **************************************************************************/
++
++/*!
++ * Handle for refering to a efx_vi
++ */
++struct efx_vi_dma_map_state;
++
++/*!
++ * Map a list of buffer pages so they are registered with the hardware
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param addrs An array of page pointers to map
++ * \param n_addrs Length of the page pointer array.  Must be a power of two.
++ * \param dmh_out Set on success to a handle used to refer to this mapping
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages,
++                       int n_pages, struct efx_vi_dma_map_state **dmh_out);
++extern int
++efx_vi_dma_map_addrs(struct efx_vi_state *vih,
++                   unsigned long long *dev_bus_addrs, int n_pages,
++                   struct efx_vi_dma_map_state **dmh_out);
++
++/*!
++ * Unmap a previously mapped set of pages so they are no longer registered
++ * with the hardware.
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param dmh The handle to identify the dma mapping
++ */
++extern void
++efx_vi_dma_unmap_pages(struct efx_vi_state *vih,
++                     struct efx_vi_dma_map_state *dmh);
++extern void
++efx_vi_dma_unmap_addrs(struct efx_vi_state *vih,
++                     struct efx_vi_dma_map_state *dmh);
++
++/*!
++ * Retrieve the buffer address of the mapping
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param dmh The handle to identify the buffer mapping
++ * \return The buffer address on success, or zero on failure
++ */
++extern unsigned
++efx_vi_dma_get_map_addr(struct efx_vi_state *vih,
++                      struct efx_vi_dma_map_state *dmh);
++
++/**************************************************************************
++ * efx_vi filter functions
++ **************************************************************************/
++
++#define EFX_VI_STATIC_FILTERS 32
++
++/*! Handle to refer to a filter instance */
++struct filter_resource_t;
++
++/*!
++ * Allocate and add a filter
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param protocol The protocol of the new filter: UDP or TCP
++ * \param ip_addr_be32 The local ip address of the filter
++ * \param port_le16 The local port of the filter
++ * \param fh_out Set on success to be a handle to refer to this filter
++ * \return Zero on success, non-zero on failure.
++ */
++extern int
++efx_vi_filter(struct efx_vi_state *vih, int protocol, unsigned ip_addr_be32,
++            int port_le16, struct filter_resource_t **fh_out);
++
++/*!
++ * Remove a filter and free resources associated with it
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param fh The handle to identify the filter
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh);
++
++/**************************************************************************
++ * efx_vi hw resources types and functions
++ **************************************************************************/
++
++/*! Constants for the type field in efx_vi_hw_resource */
++#define EFX_VI_HW_RESOURCE_TXDMAQ    0x0      /* PFN of TX DMA Q */
++#define EFX_VI_HW_RESOURCE_RXDMAQ    0x1      /* PFN of RX DMA Q */
++#define EFX_VI_HW_RESOURCE_EVQTIMER  0x4      /* Address of event q timer */
++
++/* Address of event q pointer (EF1) */
++#define EFX_VI_HW_RESOURCE_EVQPTR    0x5
++/* Address of register pointer (Falcon A) */
++#define EFX_VI_HW_RESOURCE_EVQRPTR   0x6
++/* Offset of register pointer (Falcon B) */
++#define EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET 0x7
++/* Address of mem KVA */
++#define EFX_VI_HW_RESOURCE_EVQMEMKVA 0x8
++/* PFN of doorbell page (Falcon) */
++#define EFX_VI_HW_RESOURCE_BELLPAGE  0x9
++
++/*! How large an array to allocate for the get_() functions - smaller
++  than the total number of constants as some are mutually exclusive */
++#define EFX_VI_HW_RESOURCE_MAXSIZE   0x7
++
++/*! Constants for the mem_type field in efx_vi_hw_resource */
++#define EFX_VI_HW_RESOURCE_IOBUFFER   0       /* Host memory */
++#define EFX_VI_HW_RESOURCE_PERIPHERAL 1       /* Card memory/registers */
++
++/*!
++ * Data structure providing information on a hardware resource mapping
++ */
++struct efx_vi_hw_resource {
++      u8 type;                /*!< What this resource represents */
++      u8 mem_type;            /*!< What type of memory is it in, eg,
++                               * host or iomem */
++      u8 more_to_follow;      /*!< Is this part of a multi-region resource */
++      u32 length;             /*!< Length of the resource in bytes */
++      unsigned long address;  /*!< Address of this resource */
++};
++
++/*!
++ * Metadata concerning the list of hardware resource mappings
++ */
++struct efx_vi_hw_resource_metadata {
++      int evq_order;
++      int evq_offs;
++      int evq_capacity;
++      int instance;
++      unsigned rx_capacity;
++      unsigned tx_capacity;
++      int nic_arch;
++      int nic_revision;
++      char nic_variant;
++};
++
++/*!
++ * Obtain a list of hardware resource mappings, using virtual addresses
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param mdata Pointer to a structure to receive the metadata
++ * \param hw_res_array An array to receive the list of hardware resources
++ * \param length The length of hw_res_array.  Updated on success to contain
++ * the number of entries in the supplied array that were used.
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_hw_resource_get_virt(struct efx_vi_state *vih,
++                          struct efx_vi_hw_resource_metadata *mdata,
++                          struct efx_vi_hw_resource *hw_res_array,
++                          int *length);
++
++/*!
++ * Obtain a list of hardware resource mappings, using physical addresses
++ *
++ * \param vih The handle to identify the efx_vi
++ * \param mdata Pointer to a structure to receive the metadata
++ * \param hw_res_array An array to receive the list of hardware resources
++ * \param length The length of hw_res_array.  Updated on success to contain
++ * the number of entries in the supplied array that were used.
++ * \return Zero on success, non-zero on failure
++ */
++extern int
++efx_vi_hw_resource_get_phys(struct efx_vi_state *vih,
++                          struct efx_vi_hw_resource_metadata *mdata,
++                          struct efx_vi_hw_resource *hw_res_array,
++                          int *length);
++
++#endif /* __CI_DRIVER_RESOURCE_EFX_VI_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h   2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,69 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains definition of the public type struct linux_efhw_nic.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_LINUX_RESOURCE__
++#define __CI_DRIVER_RESOURCE_LINUX_RESOURCE__
++
++#include <ci/efrm/efrm_nic.h>
++#include <linux/interrupt.h>
++
++
++/************************************************************************
++ * Per-nic structure in the resource driver                             *
++ ************************************************************************/
++
++struct linux_efhw_nic {
++      struct efrm_nic efrm_nic;
++
++      struct pci_dev *pci_dev;        /*!< pci descriptor */
++      struct tasklet_struct tasklet;  /*!< for interrupt bottom half */
++
++      /* Physical addresses of the control aperture bar. */
++      unsigned long ctr_ap_pci_addr;
++
++      /*! Callbacks for driverlink, when needed. */
++      struct efx_dl_callbacks *dl_callbacks;
++
++      /*! Event handlers. */
++      struct efhw_ev_handler *ev_handlers;
++
++};
++
++#define linux_efhw_nic(_efhw_nic)                                     \
++  container_of(_efhw_nic, struct linux_efhw_nic, efrm_nic.efhw_nic)
++
++#endif /* __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/checks.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/checks.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,118 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides helpers to turn bit shifts into dword shifts and
++ * check that the bit fields haven't overflown the dword etc.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_CHECK_H__
++#define __CI_EFHW_CHECK_H__
++
++/*----------------------------------------------------------------------------
++ *
++ * Helpers to turn bit shifts into dword shifts and check that the bit fields
++ * haven't overflown the dword etc. Aim is to preserve consistency with the
++ * autogenerated headers - once stable we could hard code.
++ *
++ *---------------------------------------------------------------------------*/
++
++/* mask constructors */
++#define __FALCON_MASK(WIDTH, T)       ((((T)1) << (WIDTH)) - 1)
++#define __FALCON_MASK32(WIDTH)        __FALCON_MASK((WIDTH), uint32_t)
++#define __FALCON_MASK64(WIDTH)        __FALCON_MASK((WIDTH), uint64_t)
++
++#define __FALCON_MASKFIELD32(LBN, WIDTH) \
++      ((uint32_t)(__FALCON_MASK32(WIDTH) << (LBN)))
++
++/* constructors for fields which span the first and second dwords */
++#define __LW(LBN)             (32 - LBN)
++#define __LOW(v, LBN, WIDTH) \
++      ((uint32_t)(((v) & __FALCON_MASK64(__LW((LBN)))) << (LBN)))
++#define __HIGH(v, LBN, WIDTH) \
++      ((uint32_t)(((v) >> __LW((LBN))) & \
++                  __FALCON_MASK64((WIDTH - __LW((LBN))))))
++/* constructors for fields within the second dword */
++#define __DW2(LBN)            ((LBN) - 32)
++
++/* constructors for fields which span the second and third dwords */
++#define __LW2(LBN)            (64 - LBN)
++#define __LOW2(v, LBN, WIDTH) \
++      ((uint32_t)(((v) & __FALCON_MASK64(__LW2((LBN)))) << ((LBN) - 32)))
++#define __HIGH2(v, LBN, WIDTH) \
++      ((uint32_t)(((v) >> __LW2((LBN))) & \
++                  __FALCON_MASK64((WIDTH - __LW2((LBN))))))
++
++/* constructors for fields within the third dword */
++#define __DW3(LBN)            ((LBN) - 64)
++
++/* constructors for fields which span the third and fourth dwords */
++#define __LW3(LBN)            (96 - LBN)
++#define __LOW3(v, LBN, WIDTH) \
++      ((uint32_t)(((v) & __FALCON_MASK64(__LW3((LBN)))) << ((LBN) - 64)))
++#define __HIGH3(v, LBN, WIDTH) \
++      ((ci_unit32)(((v) >> __LW3((LBN))) & \
++                   __FALCON_MASK64((WIDTH - __LW3((LBN))))))
++
++/* constructors for fields within the fourth dword */
++#define __DW4(LBN)            ((LBN) - 96)
++
++/* checks that the autogenerated headers are consistent with our model */
++#define __WIDTHCHCK(a, b)     EFHW_ASSERT((a) == (b))
++#define __RANGECHCK(v, WIDTH) \
++      EFHW_ASSERT(((uint64_t)(v) & ~(__FALCON_MASK64((WIDTH)))) == 0)
++
++/* fields within the first dword */
++#define __DWCHCK(LBN, WIDTH) \
++      EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 32))
++
++/* fields which span the first and second dwords */
++#define __LWCHK(LBN, WIDTH)   EFHW_ASSERT(WIDTH >= __LW(LBN))
++
++/* fields within the second dword */
++#define __DW2CHCK(LBN, WIDTH) \
++      EFHW_ASSERT(((LBN) >= 32) && (((LBN)+(WIDTH)) <= 64))
++
++/* fields which span the second and third dwords */
++#define __LW2CHK(LBN, WIDTH)  EFHW_ASSERT(WIDTH >= __LW2(LBN))
++
++/* fields within the third dword */
++#define __DW3CHCK(LBN, WIDTH) \
++      EFHW_ASSERT(((LBN) >= 64) && (((LBN)+(WIDTH)) <= 96))
++
++/* fields which span the third and fourth dwords */
++#define __LW3CHK(LBN, WIDTH)  EFHW_ASSERT(WIDTH >= __LW3(LBN))
++
++/* fields within the fourth dword */
++#define __DW4CHCK(LBN, WIDTH) \
++      EFHW_ASSERT(((LBN) >= 96) && (((LBN)+(WIDTH)) <= 128))
++
++/* fields in the first qword */
++#define __QWCHCK(LBN, WIDTH) \
++      EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 64))
++
++#endif /* __CI_EFHW_CHECK_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,93 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides API of the efhw library which may be used both from
++ * the kernel and from the user-space code.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_COMMON_H__
++#define __CI_EFHW_COMMON_H__
++
++#include <ci/efhw/common_sysdep.h>
++
++typedef uint32_t efhw_buffer_addr_t;
++#define EFHW_BUFFER_ADDR_FMT  "[ba:%"PRIx32"]"
++
++/*! Comment? */
++typedef union {
++      uint64_t u64;
++      struct {
++              uint32_t a;
++              uint32_t b;
++      } opaque;
++} efhw_event_t;
++
++/* Flags for TX/RX queues */
++#define EFHW_VI_JUMBO_EN           0x01    /*! scatter RX over multiple desc */
++#define EFHW_VI_ISCSI_RX_HDIG_EN   0x02    /*! iscsi rx header digest */
++#define EFHW_VI_ISCSI_TX_HDIG_EN   0x04    /*! iscsi tx header digest */
++#define EFHW_VI_ISCSI_RX_DDIG_EN   0x08    /*! iscsi rx data digest */
++#define EFHW_VI_ISCSI_TX_DDIG_EN   0x10    /*! iscsi tx data digest */
++#define EFHW_VI_TX_PHYS_ADDR_EN    0x20    /*! TX physical address mode */
++#define EFHW_VI_RX_PHYS_ADDR_EN    0x40    /*! RX physical address mode */
++#define EFHW_VI_RM_WITH_INTERRUPT  0x80    /*! VI with an interrupt */
++#define EFHW_VI_TX_IP_CSUM_DIS     0x100   /*! enable ip checksum generation */
++#define EFHW_VI_TX_TCPUDP_CSUM_DIS 0x200   /*! enable tcp/udp checksum
++                                             generation */
++#define EFHW_VI_TX_TCPUDP_ONLY     0x400   /*! drop non-tcp/udp packets */
++
++/* Types of hardware filter */
++/* Each of these values implicitly selects scatter filters on B0 - or in
++   EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK if a non-scatter filter is required */
++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD  (0) /* dest host only */
++#define EFHW_IP_FILTER_TYPE_UDP_FULL      (1) /* dest host and port */
++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD  (2) /* dest based filter */
++#define EFHW_IP_FILTER_TYPE_TCP_FULL      (3) /* src  filter */
++/* Same again, but with RSS (for B0 only) */
++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD_RSS_B0  (4)
++#define EFHW_IP_FILTER_TYPE_UDP_FULL_RSS_B0      (5)
++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD_RSS_B0  (6)
++#define EFHW_IP_FILTER_TYPE_TCP_FULL_RSS_B0      (7)
++
++#define EFHW_IP_FILTER_TYPE_FULL_MASK      (0x1) /* Mask for full / wildcard */
++#define EFHW_IP_FILTER_TYPE_TCP_MASK       (0x2) /* Mask for TCP type */
++#define EFHW_IP_FILTER_TYPE_RSS_B0_MASK    (0x4) /* Mask for B0 RSS enable */
++#define EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK (0x8) /* Mask for B0 SCATTER dsbl */
++
++#define EFHW_IP_FILTER_TYPE_MASK      (0xffff) /* Mask of types above */
++
++#define EFHW_IP_FILTER_BROADCAST      (0x10000) /* driverlink filter
++                                                   support */
++
++#endif /* __CI_EFHW_COMMON_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,61 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for
++ * userland-to-kernel interfaces.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_COMMON_LINUX_H__
++#define __CI_EFHW_COMMON_LINUX_H__
++
++#include <linux/types.h>
++
++/* Dirty hack, but Linux kernel does not provide DMA_ADDR_T_FMT */
++#if BITS_PER_LONG == 64 || defined(CONFIG_HIGHMEM64G)
++#define DMA_ADDR_T_FMT "%llx"
++#else
++#define DMA_ADDR_T_FMT "%x"
++#endif
++
++/* Linux kernel also does not provide PRIx32... Sigh. */
++#define PRIx32 "x"
++
++#ifdef __ia64__
++# define PRIx64 "lx"
++#else
++# define PRIx64 "llx"
++#endif
++
++#endif /* __CI_EFHW_COMMON_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/debug.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/debug.h       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,84 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides debug-related API for efhw library using Linux kernel
++ * primitives.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_DEBUG_LINUX_H__
++#define __CI_EFHW_DEBUG_LINUX_H__
++
++#define EFHW_PRINTK_PREFIX "[sfc efhw] "
++
++#define EFHW_PRINTK(level, fmt, ...) \
++      printk(level EFHW_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
++
++/* Following macros should be used with non-zero format parameters
++ * due to __VA_ARGS__ limitations.  Use "%s" with __func__ if you can't
++ * find better parameters. */
++#define EFHW_ERR(fmt, ...)     EFHW_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
++#define EFHW_WARN(fmt, ...)    EFHW_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
++#define EFHW_NOTICE(fmt, ...)  EFHW_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
++#if 0 && !defined(NDEBUG)
++#define EFHW_TRACE(fmt, ...) EFHW_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
++#else
++#define EFHW_TRACE(fmt, ...)
++#endif
++
++#ifndef NDEBUG
++#define EFHW_ASSERT(cond)  BUG_ON((cond) == 0)
++#define EFHW_DO_DEBUG(expr) expr
++#else
++#define EFHW_ASSERT(cond)
++#define EFHW_DO_DEBUG(expr)
++#endif
++
++#define EFHW_TEST(expr)                       \
++      do {                            \
++              if (unlikely(!(expr)))  \
++              BUG();                  \
++      } while (0)
++
++/* Build time asserts. We paste the line number into the type name
++ * so that the macro can be used more than once per file even if the
++ * compiler objects to multiple identical typedefs. Collisions
++ * between use in different header files is still possible. */
++#ifndef EFHW_BUILD_ASSERT
++#define __EFHW_BUILD_ASSERT_NAME(_x) __EFHW_BUILD_ASSERT_ILOATHECPP(_x)
++#define __EFHW_BUILD_ASSERT_ILOATHECPP(_x)  __EFHW_BUILD_ASSERT__ ##_x
++#define EFHW_BUILD_ASSERT(e) \
++      typedef char __EFHW_BUILD_ASSERT_NAME(__LINE__)[(e) ? 1 : -1]
++#endif
++
++#endif /* __CI_EFHW_DEBUG_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,43 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides some limits used in both kernel and userland code.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EFAB_CONFIG_H__
++#define __CI_EFHW_EFAB_CONFIG_H__
++
++#define EFHW_MAX_NR_DEVS 5    /* max number of efhw devices supported */
++
++#endif /* __CI_EFHW_EFAB_CONFIG_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h  2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,382 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides struct efhw_nic and some related types.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EFAB_TYPES_H__
++#define __CI_EFHW_EFAB_TYPES_H__
++
++#include <ci/efhw/efhw_config.h>
++#include <ci/efhw/hardware_sysdep.h>
++#include <ci/efhw/iopage_types.h>
++#include <ci/efhw/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * forward type declarations
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_nic;
++
++/*--------------------------------------------------------------------
++ *
++ * Managed interface
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_buffer_table_allocation{
++      unsigned base;
++      unsigned order;
++};
++
++struct eventq_resource_hardware {
++      /*!iobuffer allocated for eventq - can be larger than eventq */
++      struct efhw_iopages iobuff;
++      unsigned iobuff_off;
++      struct efhw_buffer_table_allocation buf_tbl_alloc;
++      int capacity;           /*!< capacity of event queue */
++};
++
++/*--------------------------------------------------------------------
++ *
++ * event queues and event driven callbacks
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_keventq {
++      int lock;
++      caddr_t evq_base;
++      int32_t evq_ptr;
++      uint32_t evq_mask;
++      unsigned instance;
++      struct eventq_resource_hardware hw;
++      struct efhw_ev_handler *ev_handlers;
++};
++
++/*--------------------------------------------------------------------
++ *
++ * filters
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_filter_spec {
++      uint dmaq_id;
++      uint32_t saddr_le32;
++      uint32_t daddr_le32;
++      uint16_t sport_le16;
++      uint16_t dport_le16;
++      unsigned tcp     : 1;
++      unsigned full    : 1;
++      unsigned rss     : 1;  /* not supported on A1 */
++      unsigned scatter : 1;  /* not supported on A1 */
++};
++
++struct efhw_filter_depth {
++      unsigned needed;
++      unsigned max;
++};
++
++struct efhw_filter_search_limits {
++      unsigned tcp_full;
++      unsigned tcp_wild;
++      unsigned udp_full;
++      unsigned udp_wild;
++};
++
++
++/**********************************************************************
++ * Portable HW interface. ***************************************
++ **********************************************************************/
++
++/*--------------------------------------------------------------------
++ *
++ * EtherFabric Functional units - configuration and control
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_func_ops {
++
++  /*-------------- Initialisation ------------ */
++
++      /*! close down all hardware functional units - leaves NIC in a safe
++         state for driver unload */
++      void (*close_hardware) (struct efhw_nic *nic);
++
++      /*! initialise all hardware functional units */
++      int (*init_hardware) (struct efhw_nic *nic,
++                            struct efhw_ev_handler *,
++                            const uint8_t *mac_addr, int non_irq_evq);
++
++  /*-------------- Interrupt support  ------------ */
++
++      /*! Main interrupt routine
++       **        This function returns,
++       **  - zero,       if the IRQ was not generated by EF1
++       **  - non-zero,   if EF1 was the source of the IRQ
++       **
++       **
++       ** opaque is an OS provided pointer for use by the OS callbacks
++       ** e.g in Windows used to indicate DPC scheduled
++       */
++      int (*interrupt) (struct efhw_nic *nic);
++
++      /*! Enable the interrupt */
++      void (*interrupt_enable) (struct efhw_nic *nic);
++
++      /*! Disable the interrupt */
++      void (*interrupt_disable) (struct efhw_nic *nic);
++
++      /*! Set interrupt moderation strategy for the given IRQ unit
++       ** val is in usec
++       */
++      void (*set_interrupt_moderation)(struct efhw_nic *nic, int evq,
++                                       uint val);
++
++  /*-------------- Event support  ------------ */
++
++      /*! Enable the given event queue
++         depending on the underlying implementation (EF1 or Falcon) then
++         either a q_base_addr in host memory, or a buffer base id should
++         be proivded
++       */
++      void (*event_queue_enable) (struct efhw_nic *nic,
++                                  uint evq,   /* evnt queue index */
++                                  uint evq_size,      /* units of #entries */
++                                  dma_addr_t q_base_addr, uint buf_base_id,
++                                  int interrupting);
++
++      /*! Disable the given event queue (and any associated timer) */
++      void (*event_queue_disable) (struct efhw_nic *nic, uint evq,
++                                   int timer_only);
++
++      /*! request wakeup from the NIC on a given event Q */
++      void (*wakeup_request) (struct efhw_nic *nic, dma_addr_t q_base_addr,
++                              int next_i, int evq);
++
++      /*! Push a SW event on a given eventQ */
++      void (*sw_event) (struct efhw_nic *nic, int data, int evq);
++
++  /*-------------- IP Filter API  ------------ */
++
++      /*! Setup a given filter - The software can request a filter_i,
++       * but some EtherFabric implementations will override with
++       * a more suitable index
++       */
++      int (*ipfilter_set) (struct efhw_nic *nic, int type,
++                           int *filter_i, int dmaq,
++                           unsigned saddr_be32, unsigned sport_be16,
++                           unsigned daddr_be32, unsigned dport_be16);
++
++      /*! Clear down a given filter */
++      void (*ipfilter_clear) (struct efhw_nic *nic, int filter_idx);
++
++  /*-------------- DMA support  ------------ */
++
++      /*! Initialise NIC state for a given TX DMAQ */
++      void (*dmaq_tx_q_init) (struct efhw_nic *nic,
++                              uint dmaq, uint evq, uint owner, uint tag,
++                              uint dmaq_size, uint buf_idx, uint flags);
++
++      /*! Initialise NIC state for a given RX DMAQ */
++      void (*dmaq_rx_q_init) (struct efhw_nic *nic,
++                              uint dmaq, uint evq, uint owner, uint tag,
++                              uint dmaq_size, uint buf_idx, uint flags);
++
++      /*! Disable a given TX DMAQ */
++      void (*dmaq_tx_q_disable) (struct efhw_nic *nic, uint dmaq);
++
++      /*! Disable a given RX DMAQ */
++      void (*dmaq_rx_q_disable) (struct efhw_nic *nic, uint dmaq);
++
++      /*! Flush a given TX DMA channel */
++      int (*flush_tx_dma_channel) (struct efhw_nic *nic, uint dmaq);
++
++      /*! Flush a given RX DMA channel */
++      int (*flush_rx_dma_channel) (struct efhw_nic *nic, uint dmaq);
++
++  /*-------------- Buffer table Support ------------ */
++
++      /*! Initialise a buffer table page */
++      void (*buffer_table_set) (struct efhw_nic *nic,
++                                dma_addr_t dma_addr,
++                                uint bufsz, uint region,
++                                int own_id, int buffer_id);
++
++      /*! Initialise a block of buffer table pages */
++      void (*buffer_table_set_n) (struct efhw_nic *nic, int buffer_id,
++                                  dma_addr_t dma_addr,
++                                  uint bufsz, uint region,
++                                  int n_pages, int own_id);
++
++      /*! Clear a block of buffer table pages */
++      void (*buffer_table_clear) (struct efhw_nic *nic, int buffer_id,
++                                  int num);
++
++      /*! Commit a buffer table update  */
++      void (*buffer_table_commit) (struct efhw_nic *nic);
++
++  /*-------------- New filter API ------------ */
++
++      /*! Set a given filter */
++      int (*filter_set) (struct efhw_nic *nic, struct efhw_filter_spec *spec,
++                         int *filter_idx_out);
++
++      /*! Clear a given filter */
++      void (*filter_clear) (struct efhw_nic *nic, int filter_idx);
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * NIC type
++ *
++ *---------------------------------------------------------------------------*/
++
++struct efhw_device_type {
++      int  arch;            /* enum efhw_arch */
++      char variant;         /* 'A', 'B', ... */
++      int  revision;        /* 0, 1, ... */
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * EtherFabric NIC instance - nic.c for HW independent functions
++ *
++ *---------------------------------------------------------------------------*/
++
++/*! */
++struct efhw_nic {
++      /*! zero base index in efrm_nic_tablep->nic array */
++      int index;
++      int ifindex;            /*!< OS level nic index */
++      struct net *nd_net;
++
++      struct efhw_device_type devtype;
++
++      /*! Options that can be set by user. */
++      unsigned options;
++# define NIC_OPT_EFTEST             0x1       /* owner is an eftest app */
++
++# define NIC_OPT_DEFAULT            0
++
++      /*! Internal flags that indicate hardware properties at runtime. */
++      unsigned flags;
++# define NIC_FLAG_NO_INTERRUPT          0x01 /* to be set at init time only */
++# define NIC_FLAG_TRY_MSI               0x02
++# define NIC_FLAG_MSI                   0x04
++# define NIC_FLAG_OS_IRQ_EN             0x08
++
++      unsigned mtu;           /*!< MAC MTU (includes MAC hdr) */
++
++      /* hardware resources */
++
++      /*! I/O address of the start of the bar */
++      volatile char __iomem *bar_ioaddr;
++
++      /*! Bar number of control aperture. */
++      unsigned ctr_ap_bar;
++      /*! Length of control aperture in bytes. */
++      unsigned ctr_ap_bytes;
++
++      uint8_t mac_addr[ETH_ALEN];     /*!< mac address  */
++
++      /*! EtherFabric Functional Units -- functions */
++      const struct efhw_func_ops *efhw_func;
++
++      /*! This lock protects a number of misc NIC resources.  It should
++       * only be used for things that can be at the bottom of the lock
++       * order.  ie. You mustn't attempt to grab any other lock while
++       * holding this one.
++       */
++      spinlock_t *reg_lock;
++      spinlock_t the_reg_lock;
++
++      int buf_commit_outstanding;     /*!< outstanding buffer commits */
++
++      /*! interrupt callbacks (hard-irq) */
++      void (*irq_handler) (struct efhw_nic *, int unit);
++
++      /*! event queues per driver */
++      struct efhw_keventq interrupting_evq;
++
++/* for marking when we are not using an IRQ unit
++      - 0 is a valid offset to an IRQ unit on EF1! */
++#define EFHW_IRQ_UNIT_UNUSED  0xffff
++      /*! interrupt unit in use for the interrupting event queue  */
++      unsigned int irq_unit;
++
++      struct efhw_keventq non_interrupting_evq;
++
++      struct efhw_iopage irq_iobuff;  /*!<  Falcon SYSERR interrupt */
++
++      /* The new driverlink infrastructure. */
++      struct efx_dl_device *net_driver_dev;
++      struct efx_dlfilt_cb_s *dlfilter_cb;
++
++      /*! Bit masks of the sizes of event queues and dma queues supported
++       * by the nic. */
++      unsigned evq_sizes;
++      unsigned rxq_sizes;
++      unsigned txq_sizes;
++
++      /* Size of filter table. */
++      unsigned ip_filter_tbl_size;
++
++      /* Number of filters currently used */
++      unsigned ip_filter_tbl_used;
++
++      /* Dynamically allocated filter state. */
++      uint8_t *filter_in_use;
++      struct efhw_filter_spec *filter_spec_cache;
++
++      /* Currently required and maximum filter table search depths. */
++      struct efhw_filter_depth tcp_full_srch;
++      struct efhw_filter_depth tcp_wild_srch;
++      struct efhw_filter_depth udp_full_srch;
++      struct efhw_filter_depth udp_wild_srch;
++
++      /* Number of event queues, DMA queues and timers. */
++      unsigned num_evqs;
++      unsigned num_dmaqs;
++      unsigned num_timers;
++};
++
++
++#define EFHW_KVA(nic)       ((nic)->bar_ioaddr)
++
++
++#endif /* __CI_EFHW_EFHW_TYPES_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,72 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/eventq.c file.  This file is not
++ * designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EVENTQ_H__
++#define __CI_EFHW_EVENTQ_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efhw/eventq_macros.h>
++
++/*! Poll the event queue. */
++extern int efhw_keventq_poll(struct efhw_nic *, struct efhw_keventq *);
++
++/*! Callbacks for handling events. */
++struct efhw_ev_handler {
++      void (*wakeup_fn)(struct efhw_nic *nic, unsigned);
++      void (*timeout_fn)(struct efhw_nic *nic, unsigned);
++      void (*dmaq_flushed_fn) (struct efhw_nic *, unsigned, int);
++};
++
++extern int efhw_keventq_ctor(struct efhw_nic *, int instance,
++                           struct efhw_keventq *, struct efhw_ev_handler *);
++extern void efhw_keventq_dtor(struct efhw_nic *, struct efhw_keventq *);
++
++extern void efhw_handle_txdmaq_flushed(struct efhw_nic *,
++                                     struct efhw_ev_handler *,
++                                     efhw_event_t *);
++extern void efhw_handle_rxdmaq_flushed(struct efhw_nic *,
++                                     struct efhw_ev_handler *,
++                                     efhw_event_t *);
++extern void efhw_handle_wakeup_event(struct efhw_nic *,
++                                   struct efhw_ev_handler *,
++                                   efhw_event_t *);
++extern void efhw_handle_timeout_event(struct efhw_nic *,
++                                    struct efhw_ev_handler *,
++                                    efhw_event_t *);
++
++#endif /* __CI_EFHW_EVENTQ_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,77 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides some event-related macros.  This file is designed for
++ * use from kernel and from the userland contexts.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_EVENTQ_MACROS_H__
++#define __CI_EFHW_EVENTQ_MACROS_H__
++
++#include <ci/efhw/common.h>
++
++/*--------------------------------------------------------------------
++ *
++ * Event Queue manipulation
++ *
++ *--------------------------------------------------------------------*/
++
++#define EFHW_EVENT_OFFSET(q, s, i)                                    \
++      (((s)->evq_ptr - (i) * (int32_t)sizeof(efhw_event_t))           \
++       & (q)->evq_mask)
++
++#define EFHW_EVENT_PTR(q, s, i)                                               \
++      ((efhw_event_t *)((q)->evq_base + EFHW_EVENT_OFFSET(q, s, i)))
++
++#define EFHW_EVENTQ_NEXT(s)                                           \
++      do { ((s)->evq_ptr += sizeof(efhw_event_t)); } while (0)
++
++#define EFHW_EVENTQ_PREV(s)                                           \
++      do { ((s)->evq_ptr -= sizeof(efhw_event_t)); } while (0)
++
++/* Be worried about this on byteswapped machines */
++/* Due to crazy chipsets, we see the event words being written in
++** arbitrary order (bug4539).  So test for presence of event must ensure
++** that both halves have changed from the null.
++*/
++#define EFHW_IS_EVENT(evp)                    \
++      (((evp)->opaque.a != (uint32_t)-1) &&   \
++       ((evp)->opaque.b != (uint32_t)-1))
++#define EFHW_CLEAR_EVENT(evp)       ((evp)->u64 = (uint64_t)-1)
++#define EFHW_CLEAR_EVENT_VALUE      0xff
++
++#define EFHW_EVENT_OVERFLOW(evq, s)                   \
++      (EFHW_IS_EVENT(EFHW_EVENT_PTR(evq, s, 1)))
++
++#endif /* __CI_EFHW_EVENTQ_MACROS_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,94 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/falcon.c file.  This file is not
++ * designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_FALCON_H__
++#define __CI_EFHW_FALCON_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efhw/common.h>
++
++/*----------------------------------------------------------------------------
++ *
++ * Locks - unfortunately required
++ *
++ *---------------------------------------------------------------------------*/
++
++#define FALCON_LOCK_DECL        irq_flags_t lock_state
++#define FALCON_LOCK_LOCK(nic) \
++      spin_lock_irqsave((nic)->reg_lock, lock_state)
++#define FALCON_LOCK_UNLOCK(nic) \
++      spin_unlock_irqrestore((nic)->reg_lock, lock_state)
++
++extern struct efhw_func_ops falcon_char_functional_units;
++
++/*! specify a pace value for a TX DMA Queue */
++extern void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace);
++
++/*! configure the pace engine */
++extern void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base,
++                              int bin_thresh);
++
++/*! confirm buffer table updates - should be used for items where
++   loss of data would be unacceptable. E.g for the buffers that back
++   an event or DMA queue */
++extern void falcon_nic_buffer_table_confirm(struct efhw_nic *nic);
++
++/*! Reset the all the TX DMA queue pointers. */
++extern void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq);
++
++extern int
++falcon_handle_char_event(struct efhw_nic *nic,
++                       struct efhw_ev_handler *h, efhw_event_t *evp);
++
++/*! Acknowledge to HW that processing is complete on a given event queue */
++extern void falcon_nic_evq_ack(struct efhw_nic *nic, uint evq,        /* evq id */
++                             uint rptr,       /* new read pointer update */
++                             bool wakeup      /* request a wakeup event if
++                                                 ptr's != */
++    );
++
++extern void
++falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id,
++                            dma_addr_t dma_addr, uint bufsz, uint region,
++                            int n_pages, int own_id);
++
++extern int falcon_nic_filter_ctor(struct efhw_nic *nic);
++
++extern void falcon_nic_filter_dtor(struct efhw_nic *nic);
++
++#endif /* __CI_EFHW_FALCON_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,58 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/falcon_hash.c file.
++ * Function declared in this file are not exported from the Linux
++ * sfc_resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_FALCON_HASH_H__
++#define __CI_EFHW_FALCON_HASH_H__
++
++extern unsigned int
++falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
++                     unsigned int dest_ip, unsigned int dest_port,
++                     int tcp, int full);
++
++extern unsigned int
++falcon_hash_function1(unsigned int key, unsigned int nfilters);
++
++extern unsigned int
++falcon_hash_function2(unsigned int key, unsigned int nfilters);
++
++extern unsigned int
++falcon_hash_iterator(unsigned int hash1, unsigned int hash2,
++                   unsigned int n_search, unsigned int nfilters);
++
++#endif /* __CI_EFHW_FALCON_HASH_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h     2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,69 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for header files
++ * with hardware-related definitions (in ci/driver/efab/hardware*).
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_HARDWARE_LINUX_H__
++#define __CI_EFHW_HARDWARE_LINUX_H__
++
++#include <linux/io.h>
++
++#ifdef __LITTLE_ENDIAN
++#define EFHW_IS_LITTLE_ENDIAN
++#elif __BIG_ENDIAN
++#define EFHW_IS_BIG_ENDIAN
++#else
++#error Unknown endianness
++#endif
++
++#ifndef readq
++static inline uint64_t __readq(volatile void __iomem *addr)
++{
++      return *(volatile uint64_t *)addr;
++}
++#define readq(x) __readq(x)
++#endif
++
++#ifndef writeq
++static inline void __writeq(uint64_t v, volatile void __iomem *addr)
++{
++      *(volatile uint64_t *)addr = v;
++}
++#define writeq(val, addr) __writeq((val), (addr))
++#endif
++
++#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,58 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains OS-independent API for allocating iopage types.
++ * The implementation of these functions is highly OS-dependent.
++ * This file is not designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_RESOURCE_IOPAGE_H__
++#define __CI_DRIVER_RESOURCE_IOPAGE_H__
++
++#include <ci/efhw/efhw_types.h>
++
++/*--------------------------------------------------------------------
++ *
++ * memory allocation
++ *
++ *--------------------------------------------------------------------*/
++
++extern int efhw_iopage_alloc(struct efhw_nic *, struct efhw_iopage *p);
++extern void efhw_iopage_free(struct efhw_nic *, struct efhw_iopage *p);
++
++extern int efhw_iopages_alloc(struct efhw_nic *, struct efhw_iopages *p,
++                            unsigned order);
++extern void efhw_iopages_free(struct efhw_nic *, struct efhw_iopages *p);
++
++#endif /* __CI_DRIVER_RESOURCE_IOPAGE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h        2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,190 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides struct efhw_page and struct efhw_iopage for Linux
++ * kernel.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_IOPAGE_LINUX_H__
++#define __CI_EFHW_IOPAGE_LINUX_H__
++
++#include <linux/gfp.h>
++#include <linux/hardirq.h>
++#include <linux/errno.h>
++#include <ci/efhw/debug.h>
++
++/*--------------------------------------------------------------------
++ *
++ * struct efhw_page: A single page of memory.  Directly mapped in the
++ * driver, and can be mapped to userlevel.
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_page {
++      unsigned long kva;
++};
++
++static inline int efhw_page_alloc(struct efhw_page *p)
++{
++      p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++      return p->kva ? 0 : -ENOMEM;
++}
++
++static inline int efhw_page_alloc_zeroed(struct efhw_page *p)
++{
++      p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++      return p->kva ? 0 : -ENOMEM;
++}
++
++static inline void efhw_page_free(struct efhw_page *p)
++{
++      free_page(p->kva);
++      EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
++}
++
++static inline char *efhw_page_ptr(struct efhw_page *p)
++{
++      return (char *)p->kva;
++}
++
++static inline unsigned efhw_page_pfn(struct efhw_page *p)
++{
++      return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline void efhw_page_mark_invalid(struct efhw_page *p)
++{
++      p->kva = 0;
++}
++
++static inline int efhw_page_is_valid(struct efhw_page *p)
++{
++      return p->kva != 0;
++}
++
++static inline void efhw_page_init_from_va(struct efhw_page *p, void *va)
++{
++      p->kva = (unsigned long)va;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * struct efhw_iopage: A single page of memory.  Directly mapped in the driver,
++ * and can be mapped to userlevel.  Can also be accessed by the NIC.
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_iopage {
++      struct efhw_page p;
++      dma_addr_t dma_addr;
++};
++
++static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *p)
++{
++      return p->dma_addr;
++}
++
++#define efhw_iopage_ptr(iop)          efhw_page_ptr(&(iop)->p)
++#define efhw_iopage_pfn(iop)          efhw_page_pfn(&(iop)->p)
++#define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p)
++#define efhw_iopage_is_valid(iop)     efhw_page_is_valid(&(iop)->p)
++
++/*--------------------------------------------------------------------
++ *
++ * struct efhw_iopages: A set of pages that are contiguous in physical
++ * memory.  Directly mapped in the driver, and can be mapped to userlevel.
++ * Can also be accessed by the NIC.
++ *
++ * NB. The O/S may be unwilling to allocate many, or even any of these.  So
++ * only use this type where the NIC really needs a physically contiguous
++ * buffer.
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_iopages {
++      caddr_t kva;
++      unsigned order;
++      dma_addr_t dma_addr;
++};
++
++static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p)
++{
++      return p->kva;
++}
++
++static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p)
++{
++      return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p)
++{
++      return p->dma_addr;
++}
++
++static inline unsigned efhw_iopages_size(struct efhw_iopages *p)
++{
++      return 1u << (p->order + PAGE_SHIFT);
++}
++
++/* struct efhw_iopage <-> struct efhw_iopages conversions for handling
++ * physically contiguous allocations in iobufsets for iSCSI.  This allows
++ * the essential information about contiguous allocations from
++ * efhw_iopages_alloc() to be saved away in the struct efhw_iopage array in
++ * an iobufset.  (Changing the iobufset resource to use a union type would
++ * involve a lot of code changes, and make the iobufset's metadata larger
++ * which could be bad as it's supposed to fit into a single page on some
++ * platforms.)
++ */
++static inline void
++efhw_iopage_init_from_iopages(struct efhw_iopage *iopage,
++                            struct efhw_iopages *iopages, unsigned pageno)
++{
++      iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages))
++          + (pageno * PAGE_SIZE);
++      iopage->dma_addr = efhw_iopages_dma_addr(iopages) +
++          (pageno * PAGE_SIZE);
++}
++
++static inline void
++efhw_iopages_init_from_iopage(struct efhw_iopages *iopages,
++                            struct efhw_iopage *iopage, unsigned order)
++{
++      iopages->kva = (caddr_t) efhw_iopage_ptr(iopage);
++      EFHW_ASSERT(iopages->kva);
++      iopages->order = order;
++      iopages->dma_addr = efhw_iopage_dma_addr(iopage);
++}
++
++#endif /* __CI_EFHW_IOPAGE_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/nic.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/nic.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,62 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains API provided by efhw/nic.c file.  This file is not
++ * designed for use outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_NIC_H__
++#define __CI_EFHW_NIC_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efhw/public.h>
++
++
++/* Convert PCI info to device type.  Returns false when device is not
++ * recognised.
++ */
++extern int efhw_device_type_init(struct efhw_device_type *dt,
++                               int vendor_id, int device_id, int revision);
++
++/* Initialise fields that do not involve touching hardware. */
++extern void efhw_nic_init(struct efhw_nic *nic, unsigned flags,
++                        unsigned options, struct efhw_device_type dev_type);
++
++/*! Destruct NIC resources */
++extern void efhw_nic_dtor(struct efhw_nic *nic);
++
++/*! Shutdown interrupts */
++extern void efhw_nic_close_interrupts(struct efhw_nic *nic);
++
++#endif /* __CI_EFHW_NIC_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/public.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/public.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,104 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API of efhw library exported from the SFC
++ * resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_PUBLIC_H__
++#define __CI_EFHW_PUBLIC_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efhw/efhw_types.h>
++
++/*! Returns true if we have some EtherFabric functional units -
++  whether configured or not */
++static inline int efhw_nic_have_functional_units(struct efhw_nic *nic)
++{
++      return nic->efhw_func != 0;
++}
++
++/*! Returns true if the EtherFabric functional units have been configured  */
++static inline int efhw_nic_have_hw(struct efhw_nic *nic)
++{
++      return efhw_nic_have_functional_units(nic) && (EFHW_KVA(nic) != 0);
++}
++
++/*! Helper function to allocate the iobuffer needed by an eventq
++ *   - it ensures the eventq has the correct alignment for the NIC
++ *
++ * \param rm        Event-queue resource manager
++ * \param instance  Event-queue instance (index)
++ * \param buf_bytes Requested size of eventq
++ * \return          < 0 if iobuffer allocation fails
++ */
++int efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic,
++                                      struct eventq_resource_hardware *h,
++                                      int evq_instance, unsigned buf_bytes);
++
++extern void falcon_nic_set_rx_usr_buf_size(struct efhw_nic *,
++                                         int rx_usr_buf_size);
++
++/*! Get RX filter search limits from RX_FILTER_CTL_REG.
++ *  use_raw_values = 0 to get actual depth of search, or 1 to get raw values
++ *  from register.
++ */
++extern void
++falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
++                                     struct efhw_filter_search_limits *lim,
++                                     int use_raw_values);
++
++/*! Set RX filter search limits in RX_FILTER_CTL_REG.
++ *  use_raw_values = 0 if specifying actual depth of search, or 1 if specifying
++ *  raw values to write to the register.
++ */
++extern void
++falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
++                                     struct efhw_filter_search_limits *lim,
++                                     int use_raw_values);
++
++
++/*! Legacy RX IP filter search depth control interface */
++extern void
++falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full,
++                           uint32_t tcp_wild,
++                           uint32_t udp_full, uint32_t udp_wild);
++
++/*! Legacy RX IP filter search depth control interface */
++extern void
++falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full,
++                           uint32_t *tcp_wild,
++                           uint32_t *udp_full, uint32_t *udp_wild);
++
++#endif /* __CI_EFHW_PUBLIC_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,55 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for efhw library.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFHW_SYSDEP_LINUX_H__
++#define __CI_EFHW_SYSDEP_LINUX_H__
++
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/vmalloc.h>
++#include <linux/if_ether.h>
++
++#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
++#include <linux/etherdevice.h>
++
++typedef unsigned long irq_flags_t;
++
++#define spin_lock_destroy(l_)  do {} while (0)
++
++#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,68 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private API for buddy allocator.  This API is not
++ * designed for use outside of SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_BUDDY_H__
++#define __CI_EFRM_BUDDY_H__
++
++#include <ci/efrm/sysdep.h>
++
++/*! Comment? */
++struct efrm_buddy_allocator {
++      struct list_head *free_lists;   /* array[order+1] */
++      struct list_head *links;        /* array[1<<order] */
++      uint8_t *orders;                /* array[1<<order] */
++      unsigned order;         /*!< total size == (1 << order) */
++      /* ?? Consider recording largest available order + for each order the
++       ** smallest available order that is big enough.
++       */
++};
++
++  /*! Returns total size of managed space. */
++static inline unsigned long efrm_buddy_size(struct efrm_buddy_allocator *b)
++{
++      return 1ul << b->order;
++}
++
++int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order);
++void efrm_buddy_dtor(struct efrm_buddy_allocator *b);
++int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order);
++void efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr,
++                   unsigned order);
++
++
++#endif /* __CI_EFRM_BUDDY_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h        2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,81 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private buffer table API.  This API is not designed
++ * for use outside of SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_BUFFER_TABLE_H__
++#define __CI_EFRM_BUFFER_TABLE_H__
++
++#include <ci/efhw/efhw_types.h>
++
++/*--------------------------------------------------------------------
++ *
++ * NIC's buffer table.
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Managed interface. */
++
++/*! construct a managed buffer table object, allocated over a region of
++ *  the NICs buffer table space
++ */
++extern int efrm_buffer_table_ctor(unsigned low, unsigned high);
++/*! destructor for above */
++extern void efrm_buffer_table_dtor(void);
++
++/*! allocate a contiguous region of buffer table space */
++extern int efrm_buffer_table_alloc(unsigned order,
++                                 struct efhw_buffer_table_allocation *a);
++
++
++/*--------------------------------------------------------------------
++ *
++ * buffer table operations through the HW independent API
++ *
++ *--------------------------------------------------------------------*/
++
++/*! free a previously allocated region of buffer table space */
++extern void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a);
++
++/*! commit the update of a buffer table entry to every NIC */
++extern void efrm_buffer_table_commit(void);
++
++extern void efrm_buffer_table_set(struct efhw_buffer_table_allocation *,
++                                struct efhw_nic *,
++                                unsigned i, dma_addr_t dma_addr, int owner);
++
++
++#endif /* __CI_EFRM_BUFFER_TABLE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/debug.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/debug.h       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,78 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides debug-related API for efrm library using Linux kernel
++ * primitives.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_DEBUG_LINUX_H__
++#define __CI_EFRM_DEBUG_LINUX_H__
++
++#define EFRM_PRINTK_PREFIX "[sfc efrm] "
++
++#define EFRM_PRINTK(level, fmt, ...) \
++      printk(level EFRM_PRINTK_PREFIX fmt "\n", __VA_ARGS__)
++
++/* Following macros should be used with non-zero format parameters
++ * due to __VA_ARGS__ limitations.  Use "%s" with __func__ if you can't
++ * find better parameters. */
++#define EFRM_ERR(fmt, ...)     EFRM_PRINTK(KERN_ERR, fmt, __VA_ARGS__)
++#define EFRM_WARN(fmt, ...)    EFRM_PRINTK(KERN_WARNING, fmt, __VA_ARGS__)
++#define EFRM_NOTICE(fmt, ...)  EFRM_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__)
++#if !defined(NDEBUG)
++#define EFRM_TRACE(fmt, ...) EFRM_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__)
++#else
++#define EFRM_TRACE(fmt, ...)
++#endif
++
++#ifndef NDEBUG
++#define EFRM_ASSERT(cond)  BUG_ON((cond) == 0)
++#define _EFRM_ASSERT(cond, file, line) \
++      do {                                                            \
++              if (unlikely(!(cond))) {                                \
++                      EFRM_ERR("assertion \"%s\" failed at %s %d",    \
++                               #cond, file, line);                    \
++                      BUG();                                          \
++              }                                                       \
++      } while (0)
++
++#define EFRM_DO_DEBUG(expr) expr
++#define EFRM_VERIFY_EQ(expr, val) EFRM_ASSERT((expr) == (val))
++#else
++#define EFRM_ASSERT(cond)
++#define EFRM_DO_DEBUG(expr)
++#define EFRM_VERIFY_EQ(expr, val) expr
++#endif
++
++#endif /* __CI_EFRM_DEBUG_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,89 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private API of efrm library to be used from the SFC
++ * resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_DRIVER_PRIVATE_H__
++#define __CI_EFRM_DRIVER_PRIVATE_H__
++
++#include <ci/efrm/resource.h>
++#include <ci/efrm/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * global variables
++ *
++ *--------------------------------------------------------------------*/
++
++/* Internal structure for resource driver */
++extern struct efrm_resource_manager *efrm_rm_table[];
++
++/*--------------------------------------------------------------------
++ *
++ * efrm_nic_table handling
++ *
++ *--------------------------------------------------------------------*/
++
++struct efrm_nic;
++
++extern void efrm_driver_ctor(void);
++extern void efrm_driver_dtor(void);
++extern int efrm_driver_register_nic(struct efrm_nic *, int nic_index,
++                                  int ifindex);
++extern int efrm_driver_unregister_nic(struct efrm_nic *);
++
++/*--------------------------------------------------------------------
++ *
++ * create/destroy resource managers
++ *
++ *--------------------------------------------------------------------*/
++
++struct vi_resource_dimensions {
++      unsigned evq_int_min, evq_int_lim;
++      unsigned evq_timer_min, evq_timer_lim;
++      unsigned rxq_min, rxq_lim;
++      unsigned txq_min, txq_lim;
++};
++
++/*! Initialise resources */
++extern int
++efrm_resources_init(const struct vi_resource_dimensions *,
++                  int buffer_table_min, int buffer_table_lim);
++
++/*! Tear down resources */
++extern void efrm_resources_fini(void);
++
++#endif /* __CI_EFRM_DRIVER_PRIVATE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,32 @@
++#ifndef __EFRM_CLIENT_H__
++#define __EFRM_CLIENT_H__
++
++
++struct efrm_client;
++
++
++struct efrm_client_callbacks {
++      /* Called before device is reset.  Callee may block. */
++      void (*pre_reset)(struct efrm_client *, void *user_data);
++      void (*stop)(struct efrm_client *, void *user_data);
++      void (*restart)(struct efrm_client *, void *user_data);
++};
++
++
++#define EFRM_IFINDEX_DEFAULT  -1
++
++
++/* NB. Callbacks may be invoked even before this returns. */
++extern int  efrm_client_get(int ifindex, struct efrm_client_callbacks *,
++                          void *user_data, struct efrm_client **client_out);
++extern void efrm_client_put(struct efrm_client *);
++
++extern struct efhw_nic *efrm_client_get_nic(struct efrm_client *);
++
++#if 0
++/* For each resource type... */
++extern void efrm_x_resource_resume(struct x_resource *);
++#endif
++
++
++#endif  /* __EFRM_CLIENT_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h    2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,26 @@
++#ifndef __EFRM_NIC_H__
++#define __EFRM_NIC_H__
++
++#include <ci/efhw/efhw_types.h>
++
++
++struct efrm_nic_per_vi {
++      unsigned long state;
++      struct vi_resource *vi;
++};
++
++
++struct efrm_nic {
++      struct efhw_nic efhw_nic;
++      struct list_head link;
++      struct list_head clients;
++      struct efrm_nic_per_vi *vis;
++};
++
++
++#define efrm_nic(_efhw_nic)                           \
++  container_of(_efhw_nic, struct efrm_nic, efhw_nic)
++
++
++
++#endif  /* __EFRM_NIC_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/filter.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/filter.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,122 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for filter resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_FILTER_H__
++#define __CI_EFRM_FILTER_H__
++
++#include <ci/efrm/resource.h>
++#include <ci/efhw/common.h>
++
++
++struct filter_resource;
++struct vi_resource;
++struct efrm_client;
++
++
++/*!
++ * Allocate filter resource.
++ *
++ * \param vi_parent VI resource to use as parent. The function takes
++ *                  reference to the VI resource on success.
++ * \param frs_out   pointer to return the new filter resource
++ *
++ * \return          status code; if non-zero, frs_out is unchanged
++ */
++extern int
++efrm_filter_resource_alloc(struct vi_resource *vi_parent,
++                         struct filter_resource **frs_out);
++
++extern void
++efrm_filter_resource_release(struct filter_resource *);
++
++
++extern int efrm_filter_resource_clear(struct filter_resource *frs);
++
++extern int __efrm_filter_resource_set(struct filter_resource *frs, int type,
++                                    unsigned saddr_be32, uint16_t sport_be16,
++                                    unsigned daddr_be32, uint16_t dport_be16);
++
++static inline int
++efrm_filter_resource_tcp_set(struct filter_resource *frs,
++                           unsigned saddr, uint16_t sport,
++                           unsigned daddr, uint16_t dport)
++{
++      int type;
++
++      EFRM_ASSERT((saddr && sport) || (!saddr && !sport));
++
++      type =
++          saddr ? EFHW_IP_FILTER_TYPE_TCP_FULL :
++          EFHW_IP_FILTER_TYPE_TCP_WILDCARD;
++
++      return __efrm_filter_resource_set(frs, type,
++                                        saddr, sport, daddr, dport);
++}
++
++static inline int
++efrm_filter_resource_udp_set(struct filter_resource *frs,
++                           unsigned saddr, uint16_t sport,
++                           unsigned daddr, uint16_t dport)
++{
++      int type;
++
++      EFRM_ASSERT((saddr && sport) || (!saddr && !sport));
++
++      type =
++          saddr ? EFHW_IP_FILTER_TYPE_UDP_FULL :
++          EFHW_IP_FILTER_TYPE_UDP_WILDCARD;
++
++      return __efrm_filter_resource_set(frs,
++                                        type, saddr, sport, daddr, dport);
++}
++
++
++extern int
++efrm_filter_resource_instance(struct filter_resource *);
++
++extern struct efrm_resource *
++efrm_filter_resource_to_resource(struct filter_resource *);
++
++extern struct filter_resource *
++efrm_filter_resource_from_resource(struct efrm_resource *);
++
++extern void
++efrm_filter_resource_free(struct filter_resource *);
++
++
++#endif /* __CI_EFRM_FILTER_H__ */
++/*! \cidoxg_end */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h    2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,110 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for iobufset resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_IOBUFSET_H__
++#define __CI_EFRM_IOBUFSET_H__
++
++#include <ci/efrm/vi_resource.h>
++
++/*! Iobufset resource structture.
++ * Users should not access the structure fields directly, but use the API
++ * below.
++ * However, this structure should not be moved out of public headers,
++ * because part of API (ex. efrm_iobufset_dma_addr function) is inline and
++ * is used in the fast-path code.
++ */
++struct iobufset_resource {
++      struct efrm_resource rs;
++      struct vi_resource *evq;
++      struct iobufset_resource *linked;
++      struct efhw_buffer_table_allocation buf_tbl_alloc;
++      unsigned int n_bufs;
++      unsigned int pages_per_contiguous_chunk;
++      unsigned chunk_order;
++      struct efhw_iopage bufs[1];
++      /*!< up to n_bufs can follow this, so this must be the last member */
++};
++
++#define iobufset_resource(rs1) \
++      container_of((rs1), struct iobufset_resource, rs)
++
++/*!
++ * Allocate iobufset resource.
++ *
++ * \param vi        VI that "owns" these buffers. Grabs a reference
++ *                  on success.
++ * \param linked    Uses memory from an existing iobufset.  Grabs a
++ *                  reference on success.
++ * \param iobrs_out pointer to return the new filter resource
++ *
++ * \return          status code; if non-zero, frs_out is unchanged
++ */
++extern int
++efrm_iobufset_resource_alloc(int32_t n_pages,
++                           int32_t pages_per_contiguous_chunk,
++                           struct vi_resource *vi,
++                           struct iobufset_resource *linked,
++                           bool phys_addr_mode,
++                           struct iobufset_resource **iobrs_out);
++
++extern void efrm_iobufset_resource_free(struct iobufset_resource *);
++extern void efrm_iobufset_resource_release(struct iobufset_resource *);
++
++static inline char *
++efrm_iobufset_ptr(struct iobufset_resource *rs, unsigned offs)
++{
++      EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT));
++      return efhw_iopage_ptr(&rs->bufs[offs >> PAGE_SHIFT])
++          + (offs & (PAGE_SIZE - 1));
++}
++
++static inline char *efrm_iobufset_page_ptr(struct iobufset_resource *rs,
++                                     unsigned page_i)
++{
++      EFRM_ASSERT(page_i < (unsigned)rs->n_bufs);
++      return efhw_iopage_ptr(&rs->bufs[page_i]);
++}
++
++static inline dma_addr_t
++efrm_iobufset_dma_addr(struct iobufset_resource *rs, unsigned offs)
++{
++      EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT));
++      return efhw_iopage_dma_addr(&rs->bufs[offs >> PAGE_SHIFT])
++          + (offs & (PAGE_SIZE - 1));
++}
++
++#endif /* __CI_EFRM_IOBUFSET_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h     2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,104 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for NIC sets.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_NIC_SET_H__
++#define __CI_EFRM_NIC_SET_H__
++
++#include <ci/efrm/debug.h>
++#include <ci/efhw/common_sysdep.h>
++#include <ci/efhw/efhw_config.h>
++
++/*--------------------------------------------------------------------
++ *
++ * efrm_nic_set_t - tracks which NICs something has been done on
++ *
++ *--------------------------------------------------------------------*/
++
++/* Internal suructure of efrm_nic_set_t should not be referenced outside of
++ * this file.  Add a new accessor if you should do it. */
++typedef struct {
++      uint32_t nics;
++} efrm_nic_set_t;
++
++#if EFHW_MAX_NR_DEVS > 32
++#error change efrm_nic_set to handle EFHW_MAX_NR_DEVS number of devices
++#endif
++
++static inline bool
++efrm_nic_set_read(const efrm_nic_set_t *nic_set, unsigned index)
++{
++      EFRM_ASSERT(nic_set);
++      EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32);
++      return (nic_set->nics & (1 << index)) ? true : false;
++}
++
++static inline void
++efrm_nic_set_write(efrm_nic_set_t *nic_set, unsigned index, bool value)
++{
++      EFRM_ASSERT(nic_set);
++      EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32);
++      EFRM_ASSERT(value == false || value == true);
++      nic_set->nics = (nic_set->nics & (~(1 << index))) + (value << index);
++}
++
++static inline void efrm_nic_set_clear(efrm_nic_set_t *nic_set)
++{
++      nic_set->nics = 0;
++}
++
++static inline void efrm_nic_set_all(efrm_nic_set_t *nic_set)
++{
++      nic_set->nics = 0xffffffff;
++}
++
++static inline bool efrm_nic_set_is_all_clear(efrm_nic_set_t *nic_set)
++{
++      return nic_set->nics == 0 ? true : false;
++}
++
++#define EFRM_NIC_SET_FMT "%x"
++
++static inline uint32_t efrm_nic_set_pri_arg(efrm_nic_set_t *nic_set)
++{
++      return nic_set->nics;
++}
++
++#define EFRM_FOR_EACH_NIC_INDEX_IN_SET(_set, _nic_i)                  \
++      for ((_nic_i) = 0; (_nic_i) < EFHW_MAX_NR_DEVS; ++(_nic_i))     \
++              if (efrm_nic_set_read((_set), (_nic_i)))
++
++#endif /* __CI_EFRM_NIC_SET_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h   2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,98 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public API for NIC table.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_NIC_TABLE_H__
++#define __CI_EFRM_NIC_TABLE_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/sysdep.h>
++
++/*--------------------------------------------------------------------
++ *
++ * struct efrm_nic_table - top level driver object keeping all NICs -
++ * implemented in driver_object.c
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Comment? */
++struct efrm_nic_table {
++      /*! nics attached to this driver */
++      struct efhw_nic *nic[EFHW_MAX_NR_DEVS];
++      /*! pointer to an arbitrary struct efhw_nic if one exists;
++       * for code which does not care which NIC it wants but
++       * still needs one. Note you cannot assume nic[0] exists. */
++      struct efhw_nic *a_nic;
++      uint32_t nic_count;     /*!< number of nics attached to this driver */
++      spinlock_t lock;        /*!< lock for table modifications */
++      atomic_t ref_count;     /*!< refcount for users of nic table */
++};
++
++/* Resource driver structures used by other drivers as well */
++extern struct efrm_nic_table *efrm_nic_tablep;
++
++static inline void efrm_nic_table_hold(void)
++{
++      atomic_inc(&efrm_nic_tablep->ref_count);
++}
++
++static inline void efrm_nic_table_rele(void)
++{
++      atomic_dec(&efrm_nic_tablep->ref_count);
++}
++
++static inline int efrm_nic_table_held(void)
++{
++      return atomic_read(&efrm_nic_tablep->ref_count) != 0;
++}
++
++/* Run code block _x multiple times with variable nic set to each
++ * registered NIC in turn.
++ * DO NOT "break" out of this loop early. */
++#define EFRM_FOR_EACH_NIC(_nic_i, _nic)                                       \
++      for ((_nic_i) = (efrm_nic_table_hold(), 0);                     \
++           (_nic_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \
++           (_nic_i)++)                                                \
++              if (((_nic) = efrm_nic_tablep->nic[_nic_i]))
++
++#define EFRM_FOR_EACH_NIC_IN_SET(_set, _i, _nic)                      \
++      for ((_i) = (efrm_nic_table_hold(), 0);                         \
++           (_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0);     \
++           ++(_i))                                                    \
++              if (((_nic) = efrm_nic_tablep->nic[_i]) &&              \
++                  efrm_nic_set_read((_set), (_i)))
++
++#endif /* __CI_EFRM_NIC_TABLE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/private.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/private.h     2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,118 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides private API of efrm library -- resource handling.
++ * This API is not designed for use outside of SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_PRIVATE_H__
++#define __CI_EFRM_PRIVATE_H__
++
++#include <ci/efrm/resource.h>
++#include <ci/efrm/driver_private.h>
++#include <ci/efrm/sysdep.h>
++#include <ci/efrm/debug.h>
++
++/*--------------------------------------------------------------------
++ *
++ * create resource managers
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Create a resource manager for various types of resources
++ */
++extern int
++efrm_create_iobufset_resource_manager(struct efrm_resource_manager **out);
++
++extern int
++efrm_create_filter_resource_manager(struct efrm_resource_manager **out);
++
++extern int
++efrm_create_vi_resource_manager(struct efrm_resource_manager **out,
++                              const struct vi_resource_dimensions *);
++
++
++/*--------------------------------------------------------------------
++ *
++ * Instance pool management
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Allocate instance pool. Use kfifo_vfree to destroy it. */
++static inline int
++efrm_kfifo_id_ctor(struct kfifo **ids_out,
++                 unsigned int base, unsigned int limit, spinlock_t *lock)
++{
++      unsigned int i;
++      struct kfifo *ids;
++      unsigned char *buffer;
++      unsigned int size = roundup_pow_of_two((limit - base) * sizeof(int));
++      EFRM_ASSERT(base <= limit);
++      buffer = vmalloc(size);
++      ids = kfifo_init(buffer, size, GFP_KERNEL, lock);
++      if (IS_ERR(ids))
++              return PTR_ERR(ids);
++      for (i = base; i < limit; i++)
++              EFRM_VERIFY_EQ(__kfifo_put(ids, (unsigned char *)&i,
++                                         sizeof(i)), sizeof(i));
++
++      *ids_out = ids;
++      return 0;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Various private functions
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Initialize the fields in the provided resource manager memory area
++ *   \param rm         The area of memory to be initialized
++ *   \param dtor       A method to destroy the resource manager
++ *   \param name       A Textual name for the resource manager
++ *   \param type       The type of resource managed
++ *   \param initial_table_size Initial size of the ID table
++ *   \param auto_destroy Destroy resource manager on driver onload iff true
++ *
++ * A default table size is provided if the value 0 is provided.
++ */
++extern int
++efrm_resource_manager_ctor(struct efrm_resource_manager *rm,
++                         void (*dtor)(struct efrm_resource_manager *),
++                         const char *name, unsigned type);
++
++extern void efrm_resource_manager_dtor(struct efrm_resource_manager *rm);
++
++
++#endif /* __CI_EFRM_PRIVATE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource.h    2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,119 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public interface of efrm library -- resource handling.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_RESOURCE_H__
++#define __CI_EFRM_RESOURCE_H__
++
++/*--------------------------------------------------------------------
++ *
++ * headers for type dependencies
++ *
++ *--------------------------------------------------------------------*/
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/resource_id.h>
++#include <ci/efrm/sysdep.h>
++#include <ci/efhw/common_sysdep.h>
++
++#ifndef __ci_driver__
++#error "Driver-only file"
++#endif
++
++/*--------------------------------------------------------------------
++ *
++ * struct efrm_resource - represents an allocated resource
++ *                   (eg. pinned pages of memory, or resource on a NIC)
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Representation of an allocated resource */
++struct efrm_resource {
++      int rs_ref_count;
++      efrm_resource_handle_t rs_handle;
++      struct efrm_client *rs_client;
++      struct list_head rs_client_link;
++      struct list_head rs_manager_link;
++};
++
++/*--------------------------------------------------------------------
++ *
++ * managed resource abstraction
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Factory for resources of a specific type */
++struct efrm_resource_manager {
++      const char *rm_name;    /*!< human readable only */
++      spinlock_t rm_lock;
++#ifndef NDEBUG
++      unsigned rm_type;
++#endif
++      int rm_resources;
++      int rm_resources_hiwat;
++      struct list_head rm_resources_list;
++      /**
++       * Destructor for the resource manager. Other resource managers
++       * might be already dead, although the system guarantees that
++       * managers are destructed in the order by which they were created
++       */
++      void (*rm_dtor)(struct efrm_resource_manager *);
++};
++
++#ifdef NDEBUG
++# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz)
++# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm)
++#else
++/*! Check validity of resource and report on failure */
++extern void efrm_resource_assert_valid(struct efrm_resource *,
++                                     int rc_may_be_zero,
++                                     const char *file, int line);
++# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz) \
++      efrm_resource_assert_valid((rs), (rc_mbz), __FILE__, __LINE__)
++
++/*! Check validity of resource manager and report on failure */
++extern void efrm_resource_manager_assert_valid(struct efrm_resource_manager *,
++                                             const char *file, int line);
++# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm) \
++      efrm_resource_manager_assert_valid((rm), __FILE__, __LINE__)
++#endif
++
++
++extern void efrm_resource_ref(struct efrm_resource *rs);
++extern int  __efrm_resource_release(struct efrm_resource *);
++
++
++#endif /* __CI_EFRM_RESOURCE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,104 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides public type and definitions resource handle, and the
++ * definitions of resource types.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFRM_RESOURCE_ID_H__
++#define __CI_DRIVER_EFRM_RESOURCE_ID_H__
++
++/***********************************************************************
++ * Resource handles
++ *
++ * Resource handles are intended for identifying resources at kernel
++ * level, within the context of a particular NIC. particularly because
++ * for some resource types, the low 16 bites correspond to hardware
++ * IDs. They were historically also used at user level, with a nonce
++ * stored in the bits 16 to 27 (inclusive), but that approach is
++ * deprecated (but sill alive!).
++ *
++ * The handle value 0 is used to mean "no resource".
++ * Identify resources within the context of a file descriptor at user
++ * level.
++ ***********************************************************************/
++
++typedef struct {
++      uint32_t handle;
++} efrm_resource_handle_t;
++
++/* You may think these following functions should all have
++ * _HANDLE_ in their names, but really we are providing an abstract set
++ * of methods on a (hypothetical) efrm_resource_t object, with
++ * efrm_resource_handle_t being just the reference one holds to access
++ * the object (aka "this" or "self").
++ */
++
++/* Below I use inline instead of macros where possible in order to get
++ * more type checking help from the compiler; hopefully we'll never
++ * have to rewrite these to use #define as we've found some horrible
++ * compiler on which we cannot make static inline do the Right Thing (tm).
++ *
++ * For consistency and to avoid pointless change I spell these
++ * routines as macro names (CAPTILIZE_UNDERSCORED), which also serves
++ * to remind people they are compact and inlined.
++ */
++
++#define EFRM_RESOURCE_FMT  "[rs:%08x]"
++
++static inline unsigned EFRM_RESOURCE_PRI_ARG(efrm_resource_handle_t h)
++{
++      return h.handle;
++}
++
++static inline unsigned EFRM_RESOURCE_INSTANCE(efrm_resource_handle_t h)
++{
++      return h.handle & 0x0000ffff;
++}
++
++static inline unsigned EFRM_RESOURCE_TYPE(efrm_resource_handle_t h)
++{
++      return (h.handle & 0xf0000000) >> 28;
++}
++
++/***********************************************************************
++ * Resource type codes
++ ***********************************************************************/
++
++#define EFRM_RESOURCE_IOBUFSET          0x0
++#define EFRM_RESOURCE_VI                0x1
++#define EFRM_RESOURCE_FILTER            0x2
++#define EFRM_RESOURCE_NUM               0x3   /* This isn't a resource! */
++
++#define       EFRM_RESOURCE_NAME(type) \
++      ((type) == EFRM_RESOURCE_IOBUFSET?      "IOBUFSET"      : \
++       (type) == EFRM_RESOURCE_VI?            "VI"            : \
++       (type) == EFRM_RESOURCE_FILTER?        "FILTER"        : \
++                                              "<invalid>")
++
++#endif /* __CI_DRIVER_EFRM_RESOURCE_ID_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,46 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides Linux-like system-independent API for efrm library.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_SYSDEP_H__
++#define __CI_EFRM_SYSDEP_H__
++
++/* Spinlocks are defined in efhw/sysdep.h */
++#include <ci/efhw/sysdep.h>
++
++#include <ci/efrm/sysdep_linux.h>
++
++#endif /* __CI_EFRM_SYSDEP_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h        2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,93 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides version-independent Linux kernel API for efrm library.
++ * Only kernels >=2.6.9 are supported.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Kfifo API is partially stolen from linux-2.6.22/include/linux/list.h
++ * Copyright (C) 2004 Stelian Pop <stelian@popies.net>
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_SYSDEP_LINUX_H__
++#define __CI_EFRM_SYSDEP_LINUX_H__
++
++#include <linux/list.h>
++#include <linux/vmalloc.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/workqueue.h>
++#include <linux/gfp.h>
++#include <linux/slab.h>
++#include <linux/hardirq.h>
++#include <linux/kernel.h>
++#include <linux/if_ether.h>
++#include <linux/completion.h>
++#include <linux/in.h>
++#include <linux/log2.h>
++#include <linux/kfifo.h>
++
++
++/********************************************************************
++ *
++ * List API
++ *
++ ********************************************************************/
++
++static inline struct list_head *list_pop(struct list_head *list)
++{
++      struct list_head *link = list->next;
++      list_del(link);
++      return link;
++}
++
++static inline struct list_head *list_pop_tail(struct list_head *list)
++{
++      struct list_head *link = list->prev;
++      list_del(link);
++      return link;
++}
++
++/********************************************************************
++ *
++ * Kfifo API
++ *
++ ********************************************************************/
++
++static inline void kfifo_vfree(struct kfifo *fifo)
++{
++      vfree(fifo->buffer);
++      kfree(fifo);
++}
++
++#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,157 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains public API for VI resource.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_VI_RESOURCE_H__
++#define __CI_EFRM_VI_RESOURCE_H__
++
++#include <ci/efhw/efhw_types.h>
++#include <ci/efrm/resource.h>
++#include <ci/efrm/debug.h>
++
++struct vi_resource;
++
++/* Make these inline instead of macros for type checking */
++static inline struct vi_resource *
++efrm_to_vi_resource(struct efrm_resource *rs)
++{
++      EFRM_ASSERT(EFRM_RESOURCE_TYPE(rs->rs_handle) == EFRM_RESOURCE_VI);
++      return (struct vi_resource *) rs;
++}
++static inline struct
++efrm_resource *efrm_from_vi_resource(struct vi_resource *rs)
++{
++      return (struct efrm_resource *)rs;
++}
++
++#define EFAB_VI_RESOURCE_INSTANCE(virs) \
++    EFRM_RESOURCE_INSTANCE(efrm_from_vi_resource(virs)->rs_handle)
++
++#define EFAB_VI_RESOURCE_PRI_ARG(virs) \
++    EFRM_RESOURCE_PRI_ARG(efrm_from_vi_resource(virs)->rs_handle)
++
++extern int
++efrm_vi_resource_alloc(struct efrm_client *client,
++                     struct vi_resource *evq_virs,
++                     uint16_t vi_flags, int32_t evq_capacity,
++                     int32_t txq_capacity, int32_t rxq_capacity,
++                     uint8_t tx_q_tag, uint8_t rx_q_tag,
++                     struct vi_resource **virs_in_out,
++                     uint32_t *out_io_mmap_bytes,
++                     uint32_t *out_mem_mmap_bytes,
++                     uint32_t *out_txq_capacity,
++                     uint32_t *out_rxq_capacity);
++
++extern void efrm_vi_resource_free(struct vi_resource *);
++extern void efrm_vi_resource_release(struct vi_resource *);
++
++
++/*--------------------------------------------------------------------
++ *
++ * eventq handling
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Reset an event queue and clear any associated timers */
++extern void efrm_eventq_reset(struct vi_resource *virs);
++
++/*! Register a kernel-level handler for the event queue.  This function is
++ * called whenever a timer expires, or whenever the event queue is woken
++ * but no thread is blocked on it.
++ *
++ * This function returns -EBUSY if a callback is already installed.
++ *
++ * \param rs      Event-queue resource
++ * \param handler Callback-handler
++ * \param arg     Argument to pass to callback-handler
++ * \return        Status code
++ */
++extern int
++efrm_eventq_register_callback(struct vi_resource *rs,
++                            void (*handler)(void *arg, int is_timeout,
++                                            struct efhw_nic *nic),
++                            void *arg);
++
++/*! Kill the kernel-level callback.
++ *
++ * This function stops the timer from running and unregisters the callback
++ * function.  It waits for any running timeout handlers to complete before
++ * returning.
++ *
++ * \param rs      Event-queue resource
++ * \return        Nothing
++ */
++extern void efrm_eventq_kill_callback(struct vi_resource *rs);
++
++/*! Ask the NIC to generate a wakeup when an event is next delivered. */
++extern void efrm_eventq_request_wakeup(struct vi_resource *rs,
++                                     unsigned current_ptr);
++
++/*! Register a kernel-level handler for flush completions.
++ * \TODO Currently, it is unsafe to install a callback more than once.
++ *
++ * \param rs      VI resource being flushed.
++ * \param handler Callback handler function.
++ * \param arg     Argument to be passed to handler.
++ */
++extern void
++efrm_vi_register_flush_callback(struct vi_resource *rs,
++                              void (*handler)(void *),
++                              void *arg);
++
++int efrm_vi_resource_flush_retry(struct vi_resource *virs);
++
++/*! Comment? */
++extern int efrm_pt_flush(struct vi_resource *);
++
++/*! Comment? */
++extern int efrm_pt_pace(struct vi_resource *, unsigned int val);
++
++uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs
++                            /*,struct efhw_nic *nic */);
++uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs
++                            /*,struct efhw_nic *nic */);
++uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs
++                            /*,struct efhw_nic *nic */);
++
++
++/* Fill [out_vi_data] with information required to allow a VI to be init'd.
++ * [out_vi_data] must ref at least VI_MAPPINGS_SIZE bytes.
++ */
++extern void efrm_vi_resource_mappings(struct vi_resource *, void *out_vi_data);
++
++
++#endif /* __CI_EFRM_VI_RESOURCE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,155 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains type definitions for VI resource.  These types
++ * may be used outside of the SFC resource driver, but such use is not
++ * recommended.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__
++#define __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efrm/vi_resource.h>
++
++
++#define EFRM_VI_RM_DMA_QUEUE_COUNT 2
++#define EFRM_VI_RM_DMA_QUEUE_TX    0
++#define EFRM_VI_RM_DMA_QUEUE_RX    1
++
++/** Numbers of bits which can be set in the evq_state member of
++ * vi_resource_evq_info. */
++enum {
++  /** This bit is set if a wakeup has been requested on the NIC. */
++      VI_RESOURCE_EVQ_STATE_WAKEUP_PENDING,
++  /** This bit is set if the wakeup is valid for the sleeping
++   * process. */
++      VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
++  /** This bit is set if a wakeup or timeout event is currently being
++   * processed. */
++      VI_RESOURCE_EVQ_STATE_BUSY,
++};
++#define VI_RESOURCE_EVQ_STATE(X) \
++      (((int32_t)1) << (VI_RESOURCE_EVQ_STATE_##X))
++
++
++/*! Global information for the VI resource manager. */
++struct vi_resource_manager {
++      struct efrm_resource_manager rm;
++
++      struct kfifo *instances_with_timer;
++      int with_timer_base;
++      int with_timer_limit;
++      struct kfifo *instances_with_interrupt;
++      int with_interrupt_base;
++      int with_interrupt_limit;
++
++      bool iscsi_dmaq_instance_is_free;
++
++      /* We keep VI resources which need flushing on these lists.  The VI
++       * is put on the outstanding list when the flush request is issued
++       * to the hardware and removed when the flush event arrives.  The
++       * hardware can only handle a limited number of RX flush requests at
++       * once, so VIs are placed in the waiting list until the flush can
++       * be issued.  Flushes can be requested by the client or internally
++       * by the VI resource manager.  In the former case, the reference
++       * count must be non-zero for the duration of the flush and in the
++       * later case, the reference count must be zero. */
++      struct list_head rx_flush_waiting_list;
++      struct list_head rx_flush_outstanding_list;
++      struct list_head tx_flush_outstanding_list;
++      int rx_flush_outstanding_count;
++
++      /* once the flush has happened we push the close into the work queue
++       * so its OK on Windows to free the resources (Bug 3469).  Resources
++       * on this list have zero reference count.
++       */
++      struct list_head close_pending;
++      struct work_struct work_item;
++      struct workqueue_struct *workqueue;
++};
++
++struct vi_resource_nic_info {
++      struct eventq_resource_hardware evq_pages;
++      struct efhw_iopages dmaq_pages[EFRM_VI_RM_DMA_QUEUE_COUNT];
++};
++
++struct vi_resource {
++      /* Some macros make the assumption that the struct efrm_resource is
++       * the first member of a struct vi_resource. */
++      struct efrm_resource rs;
++      atomic_t evq_refs;      /*!< Number of users of the event queue. */
++
++      uint32_t bar_mmap_bytes;
++      uint32_t mem_mmap_bytes;
++
++      int32_t evq_capacity;
++      int32_t dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_COUNT];
++
++      uint8_t dmaq_tag[EFRM_VI_RM_DMA_QUEUE_COUNT];
++      uint16_t flags;
++
++      /* we keep PT endpoints that have been destroyed on a list
++       * until we have seen their TX and RX DMAQs flush complete
++       * (see Bug 1217)
++       */
++      struct list_head rx_flush_link;
++      struct list_head tx_flush_link;
++      int rx_flushing;
++      int rx_flush_outstanding;
++      int tx_flushing;
++      uint64_t flush_time;
++      int flush_count;
++
++      void (*flush_callback_fn)(void *);
++      void *flush_callback_arg;
++
++      void (*evq_callback_fn) (void *arg, int is_timeout,
++                               struct efhw_nic *nic);
++      void *evq_callback_arg;
++
++      struct vi_resource *evq_virs;   /*!< EVQ for DMA queues */
++
++       struct efhw_buffer_table_allocation
++          dmaq_buf_tbl_alloc[EFRM_VI_RM_DMA_QUEUE_COUNT];
++
++      struct vi_resource_nic_info nic_info;
++};
++
++#undef vi_resource
++#define vi_resource(rs1)  container_of((rs1), struct vi_resource, rs)
++
++static inline dma_addr_t
++efrm_eventq_dma_addr(struct vi_resource *virs)
++{
++      struct eventq_resource_hardware *hw;
++      hw = &virs->nic_info.evq_pages;
++      return efhw_iopages_dma_addr(&hw->iobuff) + hw->iobuff_off;
++}
++
++#endif /* __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h 2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,65 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains private API for VI resource.  The API is not designed
++ * to be used outside of the SFC resource driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#ifndef __CI_EFRM_VI_RESOURCE_PRIVATE_H__
++#define __CI_EFRM_VI_RESOURCE_PRIVATE_H__
++
++#include <ci/efhw/common.h>
++#include <ci/efrm/vi_resource_manager.h>
++
++extern struct vi_resource_manager *efrm_vi_manager;
++
++/*************************************************************************/
++
++extern void efrm_vi_rm_delayed_free(struct work_struct *data);
++
++extern void efrm_vi_rm_salvage_flushed_vis(void);
++
++void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs);
++
++void efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_index,
++                        struct efhw_nic *nic);
++
++/*! Wakeup handler */
++extern void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned id);
++
++/*! Timeout handler */
++extern void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned id);
++
++/*! DMA flush handler */
++extern void efrm_handle_dmaq_flushed(struct efhw_nic *nic, unsigned id,
++                                 int rx_flush);
++
++/*! SRAM update handler */
++extern void efrm_handle_sram_event(struct efhw_nic *nic);
++
++#endif /* __CI_EFRM_VI_RESOURCE_PRIVATE_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/driver_object.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/driver_object.c       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,328 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains support for the global driver variables.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ * Certain parts of the driver were implemented by
++ *          Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
++ *          OKTET Labs Ltd, Russia,
++ *          http://oktetlabs.ru, <info@oktetlabs.ru>
++ *          by request of Solarflare Communications
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#include <ci/efrm/nic_table.h>
++#include <ci/efrm/resource.h>
++#include <ci/efrm/debug.h>
++#include <ci/efrm/efrm_client.h>
++#include <ci/efrm/efrm_nic.h>
++#include "efrm_internal.h"
++
++/* We use #define rather than static inline here so that the Windows
++ * "prefast" compiler can see its own locking primitive when these
++ * two function are used (and then perform extra checking where they
++ * are used)
++ *
++ * Both macros operate on an irq_flags_t
++*/
++
++#define efrm_driver_lock(irqlock_state) \
++      spin_lock_irqsave(&efrm_nic_tablep->lock, irqlock_state)
++
++#define efrm_driver_unlock(irqlock_state)             \
++      spin_unlock_irqrestore(&efrm_nic_tablep->lock,  \
++                             irqlock_state);
++
++/* These routines are all methods on the architecturally singleton
++   global variables: efrm_nic_table, efrm_rm_table.
++
++   I hope we never find a driver model that does not allow global
++   structure variables :) (but that would break almost every driver I've
++   ever seen).
++*/
++
++/*! Exported driver state */
++static struct efrm_nic_table efrm_nic_table;
++struct efrm_nic_table *efrm_nic_tablep;
++EXPORT_SYMBOL(efrm_nic_tablep);
++
++
++/* Internal table with resource managers.
++ * We'd like to not export it, but we are still using efrm_rm_table
++ * in the char driver. So, it is declared in the private header with
++ * a purpose. */
++struct efrm_resource_manager *efrm_rm_table[EFRM_RESOURCE_NUM];
++EXPORT_SYMBOL(efrm_rm_table);
++
++
++/* List of registered nics. */
++static LIST_HEAD(efrm_nics);
++
++
++void efrm_driver_ctor(void)
++{
++      efrm_nic_tablep = &efrm_nic_table;
++      spin_lock_init(&efrm_nic_tablep->lock);
++      EFRM_TRACE("%s: driver created", __func__);
++}
++
++void efrm_driver_dtor(void)
++{
++      EFRM_ASSERT(!efrm_nic_table_held());
++
++      spin_lock_destroy(&efrm_nic_tablep->lock);
++      memset(&efrm_nic_table, 0, sizeof(efrm_nic_table));
++      memset(&efrm_rm_table, 0, sizeof(efrm_rm_table));
++      EFRM_TRACE("%s: driver deleted", __func__);
++}
++
++int efrm_driver_register_nic(struct efrm_nic *rnic, int nic_index,
++                           int ifindex)
++{
++      struct efhw_nic *nic = &rnic->efhw_nic;
++      struct efrm_nic_per_vi *vis;
++      int max_vis, rc = 0;
++      irq_flags_t lock_flags;
++
++      EFRM_ASSERT(nic_index >= 0);
++      EFRM_ASSERT(ifindex >= 0);
++
++      max_vis = 4096; /* TODO: Get runtime value. */
++      vis = vmalloc(max_vis * sizeof(rnic->vis[0]));
++      if (vis == NULL) {
++              EFRM_ERR("%s: Out of memory", __func__);
++              return -ENOMEM;
++      }
++
++      efrm_driver_lock(lock_flags);
++
++      if (efrm_nic_table_held()) {
++              EFRM_ERR("%s: driver object is in use", __func__);
++              rc = -EBUSY;
++              goto done;
++      }
++
++      if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
++              EFRM_ERR("%s: filled up NIC table size %d", __func__,
++                       EFHW_MAX_NR_DEVS);
++              rc = -E2BIG;
++              goto done;
++      }
++
++      rnic->vis = vis;
++
++      EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == NULL);
++      efrm_nic_tablep->nic[nic_index] = nic;
++      nic->index = nic_index;
++      nic->ifindex = ifindex;
++
++      if (efrm_nic_tablep->a_nic == NULL)
++              efrm_nic_tablep->a_nic = nic;
++
++      efrm_nic_tablep->nic_count++;
++
++      INIT_LIST_HEAD(&rnic->clients);
++      list_add(&rnic->link, &efrm_nics);
++
++      efrm_driver_unlock(lock_flags);
++      return 0;
++
++done:
++      efrm_driver_unlock(lock_flags);
++      vfree(vis);
++      return rc;
++}
++
++int efrm_driver_unregister_nic(struct efrm_nic *rnic)
++{
++      struct efhw_nic *nic = &rnic->efhw_nic;
++      int rc = 0;
++      int nic_index = nic->index;
++      irq_flags_t lock_flags;
++
++      EFRM_ASSERT(nic_index >= 0);
++
++      efrm_driver_lock(lock_flags);
++
++      if (efrm_nic_table_held()) {
++              EFRM_ERR("%s: driver object is in use", __func__);
++              rc = -EBUSY;
++              goto done;
++      }
++      if (!list_empty(&rnic->clients)) {
++              EFRM_ERR("%s: nic has active clients", __func__);
++              rc = -EBUSY;
++              goto done;
++      }
++
++      EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == nic);
++      EFRM_ASSERT(list_empty(&rnic->clients));
++
++      list_del(&rnic->link);
++
++      nic->index = -1;
++      efrm_nic_tablep->nic[nic_index] = NULL;
++
++      --efrm_nic_tablep->nic_count;
++
++      if (efrm_nic_tablep->a_nic == nic) {
++              if (efrm_nic_tablep->nic_count == 0) {
++                      efrm_nic_tablep->a_nic = NULL;
++              } else {
++                      for (nic_index = 0; nic_index < EFHW_MAX_NR_DEVS;
++                           nic_index++) {
++                              if (efrm_nic_tablep->nic[nic_index] != NULL)
++                                      efrm_nic_tablep->a_nic =
++                                          efrm_nic_tablep->nic[nic_index];
++                      }
++                      EFRM_ASSERT(efrm_nic_tablep->a_nic);
++              }
++      }
++
++done:
++      efrm_driver_unlock(lock_flags);
++      return rc;
++}
++
++
++int efrm_nic_pre_reset(struct efhw_nic *nic)
++{
++      struct efrm_nic *rnic = efrm_nic(nic);
++      struct efrm_client *client;
++      struct efrm_resource *rs;
++      struct list_head *client_link;
++      struct list_head *rs_link;
++      irq_flags_t lock_flags;
++
++      spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++      list_for_each(client_link, &rnic->clients) {
++              client = container_of(client_link, struct efrm_client, link);
++              EFRM_ERR("%s: client %p", __func__, client);
++              if (client->callbacks->pre_reset)
++                      client->callbacks->pre_reset(client, client->user_data);
++              list_for_each(rs_link, &client->resources) {
++                      rs = container_of(rs_link, struct efrm_resource,
++                                        rs_client_link);
++                      EFRM_ERR("%s: resource %p", __func__, rs);
++                      /* TODO: mark rs defunct */
++              }
++      }
++      spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++
++      return 0;
++}
++
++
++int efrm_nic_stop(struct efhw_nic *nic)
++{
++      /* TODO */
++      return 0;
++}
++
++
++int efrm_nic_resume(struct efhw_nic *nic)
++{
++      /* TODO */
++      return 0;
++}
++
++
++static void efrm_client_nullcb(struct efrm_client *client, void *user_data)
++{
++}
++
++static struct efrm_client_callbacks efrm_null_callbacks = {
++      efrm_client_nullcb,
++      efrm_client_nullcb,
++      efrm_client_nullcb
++};
++
++
++int efrm_client_get(int ifindex, struct efrm_client_callbacks *callbacks,
++                  void *user_data, struct efrm_client **client_out)
++{
++      struct efrm_nic *n, *rnic = NULL;
++      irq_flags_t lock_flags;
++      struct list_head *link;
++      struct efrm_client *client;
++
++      if (callbacks == NULL)
++              callbacks = &efrm_null_callbacks;
++
++      client = kmalloc(sizeof(*client), GFP_KERNEL);
++      if (client == NULL)
++              return -ENOMEM;
++
++      spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++      list_for_each(link, &efrm_nics) {
++              n = container_of(link, struct efrm_nic, link);
++              if (n->efhw_nic.ifindex == ifindex || ifindex < 0) {
++                      rnic = n;
++                      break;
++              }
++      }
++      if (rnic) {
++              client->user_data = user_data;
++              client->callbacks = callbacks;
++              client->nic = &rnic->efhw_nic;
++              client->ref_count = 1;
++              INIT_LIST_HEAD(&client->resources);
++              list_add(&client->link, &rnic->clients);
++      }
++      spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++
++      if (rnic == NULL)
++              return -ENODEV;
++
++      *client_out = client;
++      return 0;
++}
++EXPORT_SYMBOL(efrm_client_get);
++
++
++void efrm_client_put(struct efrm_client *client)
++{
++      irq_flags_t lock_flags;
++
++      EFRM_ASSERT(client->ref_count > 0);
++
++      spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++      if (--client->ref_count > 0)
++              client = NULL;
++      else
++              list_del(&client->link);
++      spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++      kfree(client);
++}
++EXPORT_SYMBOL(efrm_client_put);
++
++
++struct efhw_nic *efrm_client_get_nic(struct efrm_client *client)
++{
++      return client->nic;
++}
++EXPORT_SYMBOL(efrm_client_get_nic);
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/driverlink_new.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/driverlink_new.c      2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,260 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file contains driverlink code which interacts with the sfc network
++ * driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#include "linux_resource_internal.h"
++#include "driverlink_api.h"
++#include "kernel_compat.h"
++#include <ci/efhw/falcon.h>
++
++#include <linux/rtnetlink.h>
++#include <linux/netdevice.h>
++#include <net/net_namespace.h>
++
++/* The DL driver and associated calls */
++static int efrm_dl_probe(struct efx_dl_device *efrm_dev,
++                       const struct net_device *net_dev,
++                       const struct efx_dl_device_info *dev_info,
++                       const char *silicon_rev);
++
++static void efrm_dl_remove(struct efx_dl_device *efrm_dev);
++
++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev);
++
++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok);
++
++static void efrm_dl_mtu_changed(struct efx_dl_device *, int);
++static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event);
++
++static struct efx_dl_driver efrm_dl_driver = {
++      .name = "resource",
++      .probe = efrm_dl_probe,
++      .remove = efrm_dl_remove,
++      .reset_suspend = efrm_dl_reset_suspend,
++      .reset_resume = efrm_dl_reset_resume
++};
++
++static void
++init_vi_resource_dimensions(struct vi_resource_dimensions *rd,
++                          const struct efx_dl_falcon_resources *res)
++{
++      rd->evq_timer_min = res->evq_timer_min;
++      rd->evq_timer_lim = res->evq_timer_lim;
++      rd->evq_int_min = res->evq_int_min;
++      rd->evq_int_lim = res->evq_int_lim;
++      rd->rxq_min = res->rxq_min;
++      rd->rxq_lim = res->rxq_lim;
++      rd->txq_min = res->txq_min;
++      rd->txq_lim = res->txq_lim;
++      EFRM_TRACE
++          ("Using evq_int(%d-%d) evq_timer(%d-%d) RXQ(%d-%d) TXQ(%d-%d)",
++           res->evq_int_min, res->evq_int_lim, res->evq_timer_min,
++           res->evq_timer_lim, res->rxq_min, res->rxq_lim, res->txq_min,
++           res->txq_lim);
++}
++
++static int
++efrm_dl_probe(struct efx_dl_device *efrm_dev,
++            const struct net_device *net_dev,
++            const struct efx_dl_device_info *dev_info,
++            const char *silicon_rev)
++{
++      struct vi_resource_dimensions res_dim;
++      struct efx_dl_falcon_resources *res;
++      struct linux_efhw_nic *lnic;
++      struct pci_dev *dev;
++      struct efhw_nic *nic;
++      unsigned probe_flags = 0;
++      int non_irq_evq;
++      int rc;
++
++      efrm_dev->priv = NULL;
++
++      efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
++                                struct efx_dl_falcon_resources,
++                                hdr, res);
++
++      if (res == NULL) {
++              EFRM_ERR("%s: Unable to find falcon driverlink resources",
++                       __func__);
++              return -EINVAL;
++      }
++
++      if (res->flags & EFX_DL_FALCON_USE_MSI)
++              probe_flags |= NIC_FLAG_TRY_MSI;
++
++      dev = efrm_dev->pci_dev;
++      if (res->flags & EFX_DL_FALCON_DUAL_FUNC) {
++              unsigned vendor = dev->vendor;
++              EFRM_ASSERT(dev->bus != NULL);
++              dev = NULL;
++
++              while ((dev = pci_get_device(vendor, FALCON_S_DEVID, dev))
++                     != NULL) {
++                      EFRM_ASSERT(dev->bus != NULL);
++                      /* With PCIe (since it's point to point)
++                       * the slot ID is usually 0 and
++                       * the bus ID changes NIC to NIC, so we really
++                       * need to check both. */
++                      if (PCI_SLOT(dev->devfn) ==
++                          PCI_SLOT(efrm_dev->pci_dev->devfn)
++                          && dev->bus->number ==
++                          efrm_dev->pci_dev->bus->number)
++                              break;
++              }
++              if (dev == NULL) {
++                      EFRM_ERR("%s: Unable to find falcon secondary "
++                               "PCI device.", __func__);
++                      return -ENODEV;
++              }
++              pci_dev_put(dev);
++      }
++
++      init_vi_resource_dimensions(&res_dim, res);
++
++      EFRM_ASSERT(res_dim.evq_timer_lim > res_dim.evq_timer_min);
++      res_dim.evq_timer_lim--;
++      non_irq_evq = res_dim.evq_timer_lim;
++
++      rc = efrm_nic_add(dev, probe_flags, net_dev->dev_addr, &lnic,
++                        res->biu_lock,
++                        res->buffer_table_min, res->buffer_table_lim,
++                        non_irq_evq, &res_dim);
++      if (rc != 0)
++              return rc;
++
++      nic = &lnic->efrm_nic.efhw_nic;
++      nic->mtu = net_dev->mtu + ETH_HLEN;
++      nic->net_driver_dev = efrm_dev;
++      nic->ifindex = net_dev->ifindex;
++#ifdef CONFIG_NET_NS
++      nic->nd_net = net_dev->nd_net;
++#endif
++      efrm_dev->priv = nic;
++
++      /* Register a callback so we're told when MTU changes.
++       * We dynamically allocate efx_dl_callbacks, because
++       * the callbacks that we want depends on the NIC type.
++       */
++      lnic->dl_callbacks =
++          kmalloc(sizeof(struct efx_dl_callbacks), GFP_KERNEL);
++      if (!lnic->dl_callbacks) {
++              EFRM_ERR("Out of memory (%s)", __func__);
++              efrm_nic_del(lnic);
++              return -ENOMEM;
++      }
++      memset(lnic->dl_callbacks, 0, sizeof(*lnic->dl_callbacks));
++      lnic->dl_callbacks->mtu_changed = efrm_dl_mtu_changed;
++
++      if ((res->flags & EFX_DL_FALCON_DUAL_FUNC) == 0) {
++              /* Net driver receives all management events.
++               * Register a callback to receive the ones
++               * we're interested in. */
++              lnic->dl_callbacks->event = efrm_dl_event_falcon;
++      }
++
++      rc = efx_dl_register_callbacks(efrm_dev, lnic->dl_callbacks);
++      if (rc < 0) {
++              EFRM_ERR("%s: efx_dl_register_callbacks failed (%d)",
++                       __func__, rc);
++              kfree(lnic->dl_callbacks);
++              efrm_nic_del(lnic);
++              return rc;
++      }
++
++      return 0;
++}
++
++/* When we unregister ourselves on module removal, this function will be
++ * called for all the devices we claimed */
++static void efrm_dl_remove(struct efx_dl_device *efrm_dev)
++{
++      struct efhw_nic *nic = efrm_dev->priv;
++      struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++      EFRM_TRACE("%s called", __func__);
++      if (lnic->dl_callbacks) {
++              efx_dl_unregister_callbacks(efrm_dev, lnic->dl_callbacks);
++              kfree(lnic->dl_callbacks);
++      }
++      if (efrm_dev->priv)
++              efrm_nic_del(lnic);
++      EFRM_TRACE("%s OK", __func__);
++}
++
++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev)
++{
++      EFRM_NOTICE("%s:", __func__);
++}
++
++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok)
++{
++      EFRM_NOTICE("%s: ok=%d", __func__, ok);
++}
++
++int efrm_driverlink_register(void)
++{
++      EFRM_TRACE("%s:", __func__);
++      return efx_dl_register_driver(&efrm_dl_driver);
++}
++
++void efrm_driverlink_unregister(void)
++{
++      EFRM_TRACE("%s:", __func__);
++      efx_dl_unregister_driver(&efrm_dl_driver);
++}
++
++static void efrm_dl_mtu_changed(struct efx_dl_device *efx_dev, int mtu)
++{
++      struct efhw_nic *nic = efx_dev->priv;
++
++      ASSERT_RTNL();  /* Since we're looking at efx_dl_device::port_net_dev */
++
++      EFRM_TRACE("%s: old=%d new=%d", __func__, nic->mtu, mtu + ETH_HLEN);
++      /* If this happened we must have agreed to it above */
++      nic->mtu = mtu + ETH_HLEN;
++}
++
++static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event)
++{
++      struct efhw_nic *nic = efx_dev->priv;
++      struct linux_efhw_nic *lnic = linux_efhw_nic(nic);
++      efhw_event_t *ev = p_event;
++
++      switch (FALCON_EVENT_CODE(ev)) {
++      case FALCON_EVENT_CODE_CHAR:
++              falcon_handle_char_event(nic, lnic->ev_handlers, ev);
++              break;
++      default:
++              EFRM_WARN("%s: unknown event type=%x", __func__,
++                        (unsigned)FALCON_EVENT_CODE(ev));
++              break;
++      }
++}
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/efrm_internal.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/efrm_internal.h       2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,41 @@
++#ifndef __EFRM_INTERNAL_H__
++#define __EFRM_INTERNAL_H__
++
++
++struct filter_resource {
++      struct efrm_resource rs;
++      struct vi_resource *pt;
++      int filter_idx;
++};
++
++#define filter_resource(rs1)  container_of((rs1), struct filter_resource, rs)
++
++
++struct efrm_client {
++      void *user_data;
++      struct list_head link;
++      struct efrm_client_callbacks *callbacks;
++      struct efhw_nic *nic;
++      int ref_count;
++      struct list_head resources;
++};
++
++
++extern void efrm_client_add_resource(struct efrm_client *,
++                                   struct efrm_resource *);
++
++extern int efrm_buffer_table_size(void);
++
++
++static inline void efrm_resource_init(struct efrm_resource *rs,
++                                    int type, int instance)
++{
++      EFRM_ASSERT(instance >= 0);
++      EFRM_ASSERT(type >= 0 && type < EFRM_RESOURCE_NUM);
++      rs->rs_ref_count = 1;
++      rs->rs_handle.handle = (type << 28u) |
++              (((unsigned)jiffies & 0xfff) << 16) | instance;
++}
++
++
++#endif  /* __EFRM_INTERNAL_H__ */
+Index: head-2008-07-15/drivers/net/sfc/sfc_resource/efx_vi_shm.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ head-2008-07-15/drivers/net/sfc/sfc_resource/efx_vi_shm.c  2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,707 @@
++/****************************************************************************
++ * Driver for Solarflare network controllers -
++ *          resource management for Xen backend, OpenOnload, etc
++ *           (including support for SFE4001 10GBT NIC)
++ *
++ * This file provides implementation of EFX VI API, used from Xen
++ * acceleration driver.
++ *
++ * Copyright 2005-2007: Solarflare Communications Inc,
++ *                      9501 Jeronimo Road, Suite 250,
++ *                      Irvine, CA 92618, USA
++ *
++ * Developed and maintained by Solarflare Communications:
++ *                      <linux-xen-drivers@solarflare.com>
++ *                      <onload-dev@solarflare.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation, incorporated herein by reference.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ ****************************************************************************
++ */
++
++#include "linux_resource_internal.h"
++#include <ci/efrm/vi_resource_manager.h>
++#include <ci/driver/resource/efx_vi.h>
++#include <ci/efrm/filter.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/efrm_client.h>
++#include <linux/pci.h>
++#include "kernel_compat.h"
++
++#if EFX_VI_STATIC_FILTERS
++struct filter_list_t {
++      struct filter_list_t *next;
++      struct filter_resource *fres;
++};
++#endif
++
++struct efx_vi_state {
++      struct vi_resource *vi_res;
++
++      int ifindex;
++      struct efrm_client *efrm_client;
++      struct efhw_nic *nic;
++
++      void (*callback_fn)(void *arg, int is_timeout);
++      void *callback_arg;
++
++      struct completion flush_completion;
++
++#if EFX_VI_STATIC_FILTERS
++      struct filter_list_t fres[EFX_VI_STATIC_FILTERS];
++      struct filter_list_t *free_fres;
++      struct filter_list_t *used_fres;
++#endif
++};
++
++static void efx_vi_flush_complete(void *state_void)
++{
++      struct efx_vi_state *state = (struct efx_vi_state *)state_void;
++
++      complete(&state->flush_completion);
++}
++
++static inline int alloc_ep(struct efx_vi_state *state)
++{
++      int rc;
++
++      rc = efrm_vi_resource_alloc(state->efrm_client, NULL, EFHW_VI_JUMBO_EN,
++                                  efx_vi_eventq_size,
++                                  FALCON_DMA_Q_DEFAULT_TX_SIZE,
++                                  FALCON_DMA_Q_DEFAULT_RX_SIZE,
++                                  0, 0, &state->vi_res, NULL, NULL, NULL,
++                                  NULL);
++      if (rc < 0) {
++              EFRM_ERR("%s: ERROR efrm_vi_resource_alloc error %d",
++                       __func__, rc);
++              return rc;
++      }
++
++      efrm_vi_register_flush_callback(state->vi_res, &efx_vi_flush_complete,
++                                      (void *)state);
++
++      return 0;
++}
++
++static int free_ep(struct efx_vi_state *efx_state)
++{
++      efrm_vi_resource_release(efx_state->vi_res);
++
++      return 0;
++}
++
++#if EFX_VI_STATIC_FILTERS
++static int efx_vi_alloc_static_filters(struct efx_vi_state *efx_state)
++{
++      int i;
++      int rc;
++
++      efx_state->free_fres = efx_state->used_fres = NULL;
++
++      for (i = 0; i < EFX_VI_STATIC_FILTERS; i++) {
++              rc = efrm_filter_resource_alloc(efx_state->vi_res,
++                                              &efx_state->fres[i].fres);
++              if (rc < 0) {
++                      EFRM_ERR("%s: efrm_filter_resource_alloc failed: %d",
++                           __func__, rc);
++                      while (i > 0) {
++                              i--;
++                              efrm_filter_resource_release(efx_state->
++                                                           fres[i].fres);
++                      }
++                      efx_state->free_fres = NULL;
++                      return rc;
++              }
++              efx_state->fres[i].next = efx_state->free_fres;
++              efx_state->free_fres = &efx_state->fres[i];
++      }
++
++      return 0;
++}
++#endif
++
++int efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex)
++{
++      struct efx_vi_state *efx_state;
++      int rc;
++
++      efx_state = kmalloc(sizeof(struct efx_vi_state), GFP_KERNEL);
++
++      if (!efx_state) {
++              EFRM_ERR("%s: failed to allocate memory for efx_vi_state",
++                       __func__);
++              rc = -ENOMEM;
++              goto fail;
++      }
++
++      efx_state->ifindex = ifindex;
++      rc = efrm_client_get(ifindex, NULL, NULL, &efx_state->efrm_client);
++      if (rc < 0) {
++              EFRM_ERR("%s: efrm_client_get(%d) failed: %d", __func__,
++                       ifindex, rc);
++              rc = -ENODEV;
++              goto fail_no_ifindex;
++      }
++      efx_state->nic = efrm_client_get_nic(efx_state->efrm_client);
++
++      init_completion(&efx_state->flush_completion);
++
++      /* basically allocate_pt_endpoint() */
++      rc = alloc_ep(efx_state);
++      if (rc) {
++              EFRM_ERR("%s: alloc_ep failed: %d", __func__, rc);
++              goto fail_no_pt;
++      }
++#if EFX_VI_STATIC_FILTERS
++      /*