WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 21 Feb 2008 07:11:06 -0800
Delivery-date: Fri, 22 Feb 2008 07:43:17 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1203444905 25200
# Node ID 594bfb5cbe40d04f7e2ec1cef164bc98c8aa4383
# Parent  31d71546a6442785e55d9ba2b94796701cc40276
# Parent  9dea529497fe546d25b5dc965d8161494c27d127
merge with linux-2.6.18-xen.hg
---
 MAINTAINERS                                                                   
|    7 
 buildconfigs/linux-defconfig_xen0_x86_32                                      
|    8 
 buildconfigs/linux-defconfig_xen0_x86_64                                      
|  122 
 buildconfigs/linux-defconfig_xenU_x86_32                                      
|    6 
 buildconfigs/linux-defconfig_xenU_x86_64                                      
|  670 -
 buildconfigs/linux-defconfig_xen_x86_32                                       
|    9 
 buildconfigs/linux-defconfig_xen_x86_64                                       
|   10 
 drivers/net/Kconfig                                                           
|    2 
 drivers/net/Makefile                                                          
|    2 
 drivers/net/sfc/Kconfig                                                       
|   35 
 drivers/net/sfc/Makefile                                                      
|   43 
 drivers/net/sfc/alaska.c                                                      
|  159 
 drivers/net/sfc/bitfield.h                                                    
|  544 +
 drivers/net/sfc/boards.c                                                      
|  528 +
 drivers/net/sfc/boards.h                                                      
|   51 
 drivers/net/sfc/config.h                                                      
|    1 
 drivers/net/sfc/debugfs.c                                                     
|  924 ++
 drivers/net/sfc/debugfs.h                                                     
|  172 
 drivers/net/sfc/driverlink.c                                                  
|  544 +
 drivers/net/sfc/driverlink.h                                                  
|   93 
 drivers/net/sfc/driverlink_api.h                                              
|  612 +
 drivers/net/sfc/efx.c                                                         
| 2783 +++++++
 drivers/net/sfc/efx.h                                                         
|  103 
 drivers/net/sfc/enum.h                                                        
|  117 
 drivers/net/sfc/ethtool.c                                                     
|  734 +
 drivers/net/sfc/ethtool.h                                                     
|   44 
 drivers/net/sfc/extraversion.h                                                
|    4 
 drivers/net/sfc/falcon.c                                                      
| 3708 ++++++++++
 drivers/net/sfc/falcon.h                                                      
|  177 
 drivers/net/sfc/falcon_gmac.c                                                 
|  320 
 drivers/net/sfc/falcon_hwdefs.h                                               
| 1620 ++++
 drivers/net/sfc/falcon_io.h                                                   
|  259 
 drivers/net/sfc/falcon_xmac.c                                                 
|  691 +
 drivers/net/sfc/gmii.h                                                        
|  212 
 drivers/net/sfc/i2c-direct.c                                                  
|  398 +
 drivers/net/sfc/i2c-direct.h                                                  
|  108 
 drivers/net/sfc/kernel_compat.c                                               
|  654 +
 drivers/net/sfc/kernel_compat.h                                               
|  925 ++
 drivers/net/sfc/lm87_support.c                                                
|  295 
 drivers/net/sfc/lm87_support.h                                                
|   58 
 drivers/net/sfc/mac.h                                                         
|   38 
 drivers/net/sfc/mdio_10g.c                                                    
|  441 +
 drivers/net/sfc/mdio_10g.h                                                    
|  295 
 drivers/net/sfc/mentormac.c                                                   
|  506 +
 drivers/net/sfc/mtd.c                                                         
|  602 +
 drivers/net/sfc/net_driver.h                                                  
| 1096 ++
 drivers/net/sfc/null_phy.c                                                    
|   62 
 drivers/net/sfc/phy.c                                                         
|   28 
 drivers/net/sfc/phy.h                                                         
|   90 
 drivers/net/sfc/pm8358_phy.c                                                  
|  206 
 drivers/net/sfc/rx.c                                                          
|  798 ++
 drivers/net/sfc/rx.h                                                          
|   44 
 drivers/net/sfc/selftest.c                                                    
|  815 ++
 drivers/net/sfc/selftest.h                                                    
|   67 
 drivers/net/sfc/sfc_resource/Makefile                                         
|   15 
 drivers/net/sfc/sfc_resource/assert_valid.c                                   
|   95 
 drivers/net/sfc/sfc_resource/buddy.c                                          
|  307 
 drivers/net/sfc/sfc_resource/buffer_table.c                                   
|  210 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h                        
|  199 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h                 
|   68 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h                 
|  420 +
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h     
| 1149 +++
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h     
|   75 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h    
|  155 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_grmon.h    
|  129 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h 
|   44 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_mac.h      
|  711 +
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_xgrmon.h   
|  125 
 drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h            
|   75 
 drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h                      
|  276 
 drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h              
|   76 
 drivers/net/sfc/sfc_resource/ci/efhw/checks.h                                 
|  118 
 drivers/net/sfc/sfc_resource/ci/efhw/common.h                                 
|  102 
 drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h                          
|   67 
 drivers/net/sfc/sfc_resource/ci/efhw/debug.h                                  
|   84 
 drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h                            
|   43 
 drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h                             
|  342 
 drivers/net/sfc/sfc_resource/ci/efhw/eventq.h                                 
|   73 
 drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h                          
|   81 
 drivers/net/sfc/sfc_resource/ci/efhw/falcon.h                                 
|   93 
 drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h                            
|   58 
 drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h                        
|   84 
 drivers/net/sfc/sfc_resource/ci/efhw/iopage.h                                 
|   58 
 drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h                           
|  188 
 drivers/net/sfc/sfc_resource/ci/efhw/nic.h                                    
|   62 
 drivers/net/sfc/sfc_resource/ci/efhw/public.h                                 
|   83 
 drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h                                 
|   72 
 drivers/net/sfc/sfc_resource/ci/efrm/buddy.h                                  
|   69 
 drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h                           
|   86 
 drivers/net/sfc/sfc_resource/ci/efrm/debug.h                                  
|   78 
 drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h                         
|   86 
 drivers/net/sfc/sfc_resource/ci/efrm/filter.h                                 
|  147 
 drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h                               
|  123 
 drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h                                
|  104 
 drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h                              
|   98 
 drivers/net/sfc/sfc_resource/ci/efrm/private.h                                
|  141 
 drivers/net/sfc/sfc_resource/ci/efrm/resource.h                               
|  122 
 drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h                            
|  104 
 drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h                                 
|   54 
 drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h                           
|  248 
 drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h                            
|  171 
 drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h                    
|  182 
 drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h                    
|   83 
 drivers/net/sfc/sfc_resource/driver_object.c                                  
|  174 
 drivers/net/sfc/sfc_resource/driverlink_new.c                                 
|  290 
 drivers/net/sfc/sfc_resource/efx_vi_shm.c                                     
|  701 +
 drivers/net/sfc/sfc_resource/eventq.c                                         
|  320 
 drivers/net/sfc/sfc_resource/falcon.c                                         
| 2758 +++++++
 drivers/net/sfc/sfc_resource/falcon_hash.c                                    
|  178 
 drivers/net/sfc/sfc_resource/falcon_mac.c                                     
|  171 
 drivers/net/sfc/sfc_resource/filter_resource.c                                
|  317 
 drivers/net/sfc/sfc_resource/iobufset_resource.c                              
|  373 +
 drivers/net/sfc/sfc_resource/iopage.c                                         
|  101 
 drivers/net/sfc/sfc_resource/kernel_compat.c                                  
|  584 +
 drivers/net/sfc/sfc_resource/kernel_compat.h                                  
|  239 
 drivers/net/sfc/sfc_resource/kernel_proc.c                                    
|  111 
 drivers/net/sfc/sfc_resource/kfifo.c                                          
|  212 
 drivers/net/sfc/sfc_resource/linux_resource_internal.h                        
|   75 
 drivers/net/sfc/sfc_resource/nic.c                                            
|  190 
 drivers/net/sfc/sfc_resource/resource_driver.c                                
|  640 +
 drivers/net/sfc/sfc_resource/resource_manager.c                               
|  263 
 drivers/net/sfc/sfc_resource/resources.c                                      
|   94 
 drivers/net/sfc/sfc_resource/vi_resource_alloc.c                              
|  876 ++
 drivers/net/sfc/sfc_resource/vi_resource_event.c                              
|  232 
 drivers/net/sfc/sfc_resource/vi_resource_flush.c                              
|  506 +
 drivers/net/sfc/sfc_resource/vi_resource_manager.c                            
|  259 
 drivers/net/sfc/sfe4001.c                                                     
|  315 
 drivers/net/sfc/spi.h                                                         
|  186 
 drivers/net/sfc/tenxpress.c                                                   
|  695 +
 drivers/net/sfc/tx.c                                                          
|  522 +
 drivers/net/sfc/tx.h                                                          
|   41 
 drivers/net/sfc/txc43128_phy.c                                                
|  725 +
 drivers/net/sfc/workarounds.h                                                 
|   97 
 drivers/net/sfc/xenpack.h                                                     
|   80 
 drivers/net/sfc/xfp_phy.c                                                     
|  206 
 drivers/xen/Kconfig                                                           
|   16 
 drivers/xen/Makefile                                                          
|    3 
 drivers/xen/core/smpboot.c                                                    
|    9 
 drivers/xen/sfc_netback/Makefile                                              
|   12 
 drivers/xen/sfc_netback/accel.c                                               
|  129 
 drivers/xen/sfc_netback/accel.h                                               
|  393 +
 drivers/xen/sfc_netback/accel_debugfs.c                                       
|  170 
 drivers/xen/sfc_netback/accel_fwd.c                                           
|  415 +
 drivers/xen/sfc_netback/accel_msg.c                                           
|  392 +
 drivers/xen/sfc_netback/accel_solarflare.c                                    
| 1253 +++
 drivers/xen/sfc_netback/accel_solarflare.h                                    
|   88 
 drivers/xen/sfc_netback/accel_xenbus.c                                        
|  831 ++
 drivers/xen/sfc_netback/ci/compat.h                                           
|   53 
 drivers/xen/sfc_netback/ci/compat/gcc.h                                       
|  158 
 drivers/xen/sfc_netback/ci/compat/gcc_x86.h                                   
|  115 
 drivers/xen/sfc_netback/ci/compat/primitive.h                                 
|   77 
 drivers/xen/sfc_netback/ci/compat/sysdep.h                                    
|  166 
 drivers/xen/sfc_netback/ci/compat/utils.h                                     
|  269 
 drivers/xen/sfc_netback/ci/compat/x86.h                                       
|   48 
 drivers/xen/sfc_netback/ci/compat/x86_64.h                                    
|   54 
 drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h                           
|  276 
 drivers/xen/sfc_netback/ci/efhw/common.h                                      
|  102 
 drivers/xen/sfc_netback/ci/efhw/common_sysdep.h                               
|   67 
 drivers/xen/sfc_netback/ci/efhw/debug.h                                       
|   84 
 drivers/xen/sfc_netback/ci/efhw/efhw_config.h                                 
|   43 
 drivers/xen/sfc_netback/ci/efhw/efhw_types.h                                  
|  342 
 drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h                             
|   84 
 drivers/xen/sfc_netback/ci/efhw/iopage_types.h                                
|  188 
 drivers/xen/sfc_netback/ci/efhw/public.h                                      
|   83 
 drivers/xen/sfc_netback/ci/efhw/sysdep.h                                      
|   72 
 drivers/xen/sfc_netback/ci/efrm/nic_table.h                                   
|   98 
 drivers/xen/sfc_netback/ci/efrm/sysdep.h                                      
|   54 
 drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h                                
|  248 
 drivers/xen/sfc_netback/ci/tools/config.h                                     
|   49 
 drivers/xen/sfc_netback/ci/tools/debug.h                                      
|  336 
 drivers/xen/sfc_netback/ci/tools/log.h                                        
|  262 
 drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h                           
|  361 
 drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h                      
|  362 
 drivers/xen/sfc_netback/ci/tools/sysdep.h                                     
|  132 
 drivers/xen/sfc_netfront/Makefile                                             
|   11 
 drivers/xen/sfc_netfront/accel.h                                              
|  477 +
 drivers/xen/sfc_netfront/accel_bufs.c                                         
|  393 +
 drivers/xen/sfc_netfront/accel_bufs.h                                         
|  181 
 drivers/xen/sfc_netfront/accel_debugfs.c                                      
|  234 
 drivers/xen/sfc_netfront/accel_msg.c                                          
|  566 +
 drivers/xen/sfc_netfront/accel_netfront.c                                     
|  318 
 drivers/xen/sfc_netfront/accel_ssr.c                                          
|  308 
 drivers/xen/sfc_netfront/accel_ssr.h                                          
|   88 
 drivers/xen/sfc_netfront/accel_tso.c                                          
|  512 +
 drivers/xen/sfc_netfront/accel_tso.h                                          
|   57 
 drivers/xen/sfc_netfront/accel_vi.c                                           
| 1194 +++
 drivers/xen/sfc_netfront/accel_xenbus.c                                       
|  776 ++
 drivers/xen/sfc_netfront/ef_vi_falcon.h                                       
|  172 
 drivers/xen/sfc_netfront/ef_vi_falcon_core.h                                  
| 1075 ++
 drivers/xen/sfc_netfront/ef_vi_falcon_desc.h                                  
|   43 
 drivers/xen/sfc_netfront/ef_vi_falcon_event.h                                 
|  123 
 drivers/xen/sfc_netfront/ef_vi_internal.h                                     
|  256 
 drivers/xen/sfc_netfront/etherfabric/ef_vi.h                                  
|  665 +
 drivers/xen/sfc_netfront/falcon_event.c                                       
|  346 
 drivers/xen/sfc_netfront/falcon_vi.c                                          
|  465 +
 drivers/xen/sfc_netfront/pt_tx.c                                              
|   91 
 drivers/xen/sfc_netfront/sysdep.h                                             
|  184 
 drivers/xen/sfc_netfront/vi_init.c                                            
|  183 
 drivers/xen/sfc_netutil/Makefile                                              
|   10 
 drivers/xen/sfc_netutil/accel_cuckoo_hash.c                                   
|  651 +
 drivers/xen/sfc_netutil/accel_cuckoo_hash.h                                   
|  227 
 drivers/xen/sfc_netutil/accel_msg_iface.c                                     
|  301 
 drivers/xen/sfc_netutil/accel_msg_iface.h                                     
|  414 +
 drivers/xen/sfc_netutil/accel_shared_fifo.h                                   
|  127 
 drivers/xen/sfc_netutil/accel_util.c                                          
|  333 
 drivers/xen/sfc_netutil/accel_util.h                                          
|  127 
 206 files changed, 61232 insertions(+), 574 deletions(-)

diff -r 31d71546a644 -r 594bfb5cbe40 MAINTAINERS
--- a/MAINTAINERS       Thu Feb 14 09:35:01 2008 -0700
+++ b/MAINTAINERS       Tue Feb 19 11:15:05 2008 -0700
@@ -2558,6 +2558,13 @@ L:       linux-ia64@xxxxxxxxxxxxxxx
 L:     linux-ia64@xxxxxxxxxxxxxxx
 S:     Supported
 
+SFC NETWORK DRIVER
+P:     Steve Hodgson
+P:     Ben Hutchings
+P:     Robert Stonehouse
+M:     linux-net-drivers@xxxxxxxxxxxxxx
+S:     Supported
+
 SGI VISUAL WORKSTATION 320 AND 540
 P:     Andrey Panin
 M:     pazke@xxxxxxxxx
diff -r 31d71546a644 -r 594bfb5cbe40 buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32  Thu Feb 14 09:35:01 2008 -0700
+++ b/buildconfigs/linux-defconfig_xen0_x86_32  Tue Feb 19 11:15:05 2008 -0700
@@ -752,6 +752,7 @@ CONFIG_BNX2=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_SFC is not set
 
 #
 # Token Ring devices
@@ -1392,7 +1393,7 @@ CONFIG_CRYPTO_CRC32C=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030206
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
 
 #
 # XEN
@@ -1406,6 +1407,8 @@ CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_NETDEV_BACKEND=y
 # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
 # CONFIG_XEN_NETDEV_LOOPBACK is not set
 CONFIG_XEN_PCIDEV_BACKEND=y
 # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -1416,6 +1419,8 @@ CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_GRANT_DEV=y
+# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
@@ -1429,7 +1434,6 @@ CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_DEVMEM=y
-CONFIG_XEN_GRANT_DEV=y
 
 #
 # Library routines
diff -r 31d71546a644 -r 594bfb5cbe40 buildconfigs/linux-defconfig_xen0_x86_64
--- a/buildconfigs/linux-defconfig_xen0_x86_64  Thu Feb 14 09:35:01 2008 -0700
+++ b/buildconfigs/linux-defconfig_xen0_x86_64  Tue Feb 19 11:15:05 2008 -0700
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18.8
-# Tue Oct 16 09:32:39 2007
+# Mon Feb 18 10:41:04 2008
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -26,7 +26,7 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNA
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
@@ -41,6 +41,7 @@ CONFIG_SYSVIPC=y
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -74,6 +75,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
 
 #
 # Block layer
@@ -111,16 +113,17 @@ CONFIG_X86_INTERNODE_CACHE_BYTES=128
 CONFIG_X86_INTERNODE_CACHE_BYTES=128
 CONFIG_X86_GOOD_APIC=y
 CONFIG_MICROCODE=y
-# CONFIG_X86_MSR is not set
-# CONFIG_X86_CPUID is not set
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_XEN_GENAPIC=y
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_MTRR=y
-# CONFIG_SMP is not set
+CONFIG_SMP=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -131,6 +134,8 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_SWIOTLB=y
 CONFIG_KEXEC=y
@@ -142,10 +147,10 @@ CONFIG_HZ_100=y
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
 # CONFIG_REORDER is not set
-CONFIG_K8_NB=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Power management options
@@ -154,6 +159,7 @@ CONFIG_PM_LEGACY=y
 CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
 # CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SUSPEND_SMP=y
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
@@ -166,20 +172,22 @@ CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_VIDEO=m
-# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_HOTKEY=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_DOCK=m
 CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
 CONFIG_ACPI_ASUS=m
 CONFIG_ACPI_IBM=m
 CONFIG_ACPI_TOSHIBA=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
 CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_EC=y
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_CONTAINER is not set
+CONFIG_ACPI_CONTAINER=m
 CONFIG_ACPI_PV_SLEEP=y
 
 #
@@ -192,7 +200,7 @@ CONFIG_ACPI_PV_SLEEP=y
 #
 CONFIG_PCI=y
 CONFIG_PCI_DIRECT=y
-# CONFIG_PCI_MMCONFIG is not set
+CONFIG_PCI_MMCONFIG=y
 CONFIG_XEN_PCIDEV_FRONTEND=y
 # CONFIG_XEN_PCIDEV_FE_DEBUG is not set
 # CONFIG_PCIEPORTBUS is not set
@@ -212,9 +220,9 @@ CONFIG_XEN_PCIDEV_FRONTEND=y
 # Executable file formats / Emulations
 #
 CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
+# CONFIG_BINFMT_MISC is not set
 CONFIG_IA32_EMULATION=y
-# CONFIG_IA32_AOUT is not set
+CONFIG_IA32_AOUT=y
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 
@@ -230,6 +238,8 @@ CONFIG_PACKET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -248,8 +258,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
@@ -343,8 +353,8 @@ CONFIG_LLC=y
 #
 # Generic Driver Options
 #
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 CONFIG_SYS_HYPERVISOR=y
@@ -392,7 +402,7 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
@@ -491,7 +501,7 @@ CONFIG_BLK_DEV_SD=y
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
-CONFIG_SCSI_ISCSI_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
 
 #
@@ -505,7 +515,6 @@ CONFIG_SCSI_AIC7XXX=y
 CONFIG_SCSI_AIC7XXX=y
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
 CONFIG_AIC7XXX_DEBUG_ENABLE=y
 CONFIG_AIC7XXX_DEBUG_MASK=0
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
@@ -513,7 +522,6 @@ CONFIG_SCSI_AIC79XX=y
 CONFIG_SCSI_AIC79XX=y
 CONFIG_AIC79XX_CMDS_PER_DEVICE=32
 CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
 # CONFIG_AIC79XX_ENABLE_RD_STRM is not set
 CONFIG_AIC79XX_DEBUG_ENABLE=y
 CONFIG_AIC79XX_DEBUG_MASK=0
@@ -540,8 +548,7 @@ CONFIG_SCSI_SATA_SIL24=y
 # CONFIG_SCSI_SATA_VIA is not set
 # CONFIG_SCSI_SATA_VITESSE is not set
 CONFIG_SCSI_SATA_INTEL_COMBINED=y
-CONFIG_SCSI_BUSLOGIC=y
-# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -563,21 +570,19 @@ CONFIG_SCSI_BUSLOGIC=y
 #
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
+# CONFIG_MD_LINEAR is not set
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID456=y
-# CONFIG_MD_RAID5_RESHAPE is not set
-CONFIG_MD_MULTIPATH=y
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
+# CONFIG_DM_CRYPT is not set
 CONFIG_DM_SNAPSHOT=y
 CONFIG_DM_MIRROR=y
 # CONFIG_DM_ZERO is not set
-CONFIG_DM_MULTIPATH=y
-CONFIG_DM_MULTIPATH_EMC=y
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -698,6 +703,7 @@ CONFIG_BNX2=y
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_SFC is not set
 
 #
 # Token Ring devices
@@ -785,7 +791,7 @@ CONFIG_VT=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -811,7 +817,8 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -819,16 +826,18 @@ CONFIG_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 CONFIG_AGP=m
-CONFIG_AGP_AMD64=m
-# CONFIG_AGP_INTEL is not set
+# CONFIG_AGP_AMD64 is not set
+CONFIG_AGP_INTEL=m
 CONFIG_AGP_SIS=m
 CONFIG_AGP_VIA=m
 CONFIG_DRM=m
 CONFIG_DRM_TDFX=m
 CONFIG_DRM_R128=m
 CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
 CONFIG_DRM_MGA=m
 CONFIG_DRM_SIS=m
 # CONFIG_DRM_VIA is not set
@@ -1027,8 +1036,7 @@ CONFIG_USB_MON=y
 #
 # LED devices
 #
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
+# CONFIG_NEW_LEDS is not set
 
 #
 # LED drivers
@@ -1037,25 +1045,11 @@ CONFIG_LEDS_CLASS=m
 #
 # LED Triggers
 #
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_IDE_DISK=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 
 #
 # InfiniBand support
 #
-CONFIG_INFINIBAND=y
-# CONFIG_INFINIBAND_USER_MAD is not set
-# CONFIG_INFINIBAND_USER_ACCESS is not set
-CONFIG_INFINIBAND_ADDR_TRANS=y
-CONFIG_INFINIBAND_MTHCA=y
-CONFIG_INFINIBAND_MTHCA_DEBUG=y
-CONFIG_INFINIBAND_IPOIB=y
-CONFIG_INFINIBAND_IPOIB_DEBUG=y
-CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
-CONFIG_INFINIBAND_SRP=y
-CONFIG_INFINIBAND_ISER=y
+# CONFIG_INFINIBAND is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1079,11 +1073,11 @@ CONFIG_RTC_INTF_DEV=m
 #
 # RTC drivers
 #
-CONFIG_RTC_DRV_DS1553=m
-CONFIG_RTC_DRV_DS1742=m
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
 CONFIG_RTC_DRV_M48T86=m
 CONFIG_RTC_DRV_TEST=m
-CONFIG_RTC_DRV_V3020=m
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
 # DMA Engine support
@@ -1148,9 +1142,9 @@ CONFIG_ZISOFS_FS=y
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
@@ -1275,7 +1269,7 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
@@ -1289,7 +1283,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
@@ -1340,7 +1334,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030206
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
 
 #
 # XEN
@@ -1354,6 +1348,8 @@ CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_NETDEV_BACKEND=y
 # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
 # CONFIG_XEN_NETDEV_LOOPBACK is not set
 CONFIG_XEN_PCIDEV_BACKEND=y
 # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -1361,9 +1357,11 @@ CONFIG_XEN_PCIDEV_BACKEND_PASS=y
 # CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
 # CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set
 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
-CONFIG_XEN_TPMDEV_BACKEND=m
+# CONFIG_XEN_TPMDEV_BACKEND is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_GRANT_DEV=y
+# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
@@ -1374,9 +1372,9 @@ CONFIG_XEN_COMPAT=0x030002
 CONFIG_XEN_COMPAT=0x030002
 CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
 CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_DEVMEM=y
-CONFIG_XEN_GRANT_DEV=y
 
 #
 # Library routines
@@ -1384,6 +1382,6 @@ CONFIG_XEN_GRANT_DEV=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
+CONFIG_LIBCRC32C=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
diff -r 31d71546a644 -r 594bfb5cbe40 buildconfigs/linux-defconfig_xenU_x86_32
--- a/buildconfigs/linux-defconfig_xenU_x86_32  Thu Feb 14 09:35:01 2008 -0700
+++ b/buildconfigs/linux-defconfig_xenU_x86_32  Tue Feb 19 11:15:05 2008 -0700
@@ -903,7 +903,7 @@ CONFIG_CRYPTO_CRC32C=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030206
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
 
 #
 # XEN
@@ -913,8 +913,11 @@ CONFIG_XEN_PRIVCMD=y
 CONFIG_XEN_PRIVCMD=y
 CONFIG_XEN_XENBUS_DEV=y
 # CONFIG_XEN_BACKEND is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_XEN_GRANT_DEV is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
@@ -928,7 +931,6 @@ CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_DEVMEM=y
-# CONFIG_XEN_GRANT_DEV is not set
 
 #
 # Library routines
diff -r 31d71546a644 -r 594bfb5cbe40 buildconfigs/linux-defconfig_xenU_x86_64
--- a/buildconfigs/linux-defconfig_xenU_x86_64  Thu Feb 14 09:35:01 2008 -0700
+++ b/buildconfigs/linux-defconfig_xenU_x86_64  Tue Feb 19 11:15:05 2008 -0700
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18.8
-# Tue Oct 16 09:32:52 2007
+# Mon Feb 18 10:42:42 2008
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -36,12 +36,10 @@ CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
+# CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
 # CONFIG_RELAY is not set
@@ -52,7 +50,7 @@ CONFIG_SYSCTL=y
 CONFIG_SYSCTL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
-CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -74,7 +72,7 @@ CONFIG_MODULES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
+# CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
@@ -82,7 +80,7 @@ CONFIG_STOP_MACHINE=y
 #
 # Block layer
 #
-CONFIG_LBD=y
+# CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 CONFIG_LSF=y
 
@@ -105,8 +103,8 @@ CONFIG_X86_PC=y
 CONFIG_X86_PC=y
 # CONFIG_X86_VSMP is not set
 # CONFIG_MK8 is not set
-CONFIG_MPSC=y
-# CONFIG_GENERIC_CPU is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
 CONFIG_X86_64_XEN=y
 CONFIG_X86_NO_TSS=y
 CONFIG_X86_NO_IDT=y
@@ -133,8 +131,8 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
-CONFIG_NR_CPUS=16
-# CONFIG_HOTPLUG_CPU is not set
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_SWIOTLB=y
 # CONFIG_CRASH_DUMP is not set
@@ -168,9 +166,9 @@ CONFIG_GENERIC_PENDING_IRQ=y
 # Executable file formats / Emulations
 #
 CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
+# CONFIG_BINFMT_MISC is not set
 CONFIG_IA32_EMULATION=y
-# CONFIG_IA32_AOUT is not set
+CONFIG_IA32_AOUT=y
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 
@@ -184,146 +182,38 @@ CONFIG_NET=y
 #
 # CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
+# CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=m
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
 CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_ASK_IP_FIB_HASH=y
-# CONFIG_IP_FIB_TRIE is not set
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
-CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_TUNNEL=m
-CONFIG_INET_TUNNEL=m
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-# CONFIG_IPV6_ROUTER_PREF is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NETFILTER_XTABLES is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
-CONFIG_IP_NF_QUEUE=m
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP6_NF_QUEUE is not set
-
-#
-# Bridge: Netfilter Configuration
-#
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-# CONFIG_BRIDGE_EBT_ULOG is not set
+# CONFIG_NETFILTER is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -333,167 +223,37 @@ CONFIG_BRIDGE_EBT_LOG=m
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_IP_SCTP is not set
 
 #
 # TIPC Configuration (EXPERIMENTAL)
 #
 # CONFIG_TIPC is not set
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-# CONFIG_ATM_MPOA is not set
-CONFIG_ATM_BR2684=m
-# CONFIG_ATM_BR2684_IPFILTER is not set
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
-CONFIG_LLC=m
 # CONFIG_LLC2 is not set
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=m
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
+# CONFIG_WAN_ROUTER is not set
 
 #
 # QoS and/or fair queueing
 #
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CLK_JIFFIES=y
-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-# CONFIG_NET_SCH_CLK_CPU is not set
-
-#
-# Queueing/Scheduling
-#
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-
-#
-# Classification
-#
-CONFIG_NET_CLS=y
-# CONFIG_NET_CLS_BASIC is not set
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_CLS_U32_PERF=y
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
-CONFIG_NET_CLS_POLICE=y
-CONFIG_NET_CLS_IND=y
-CONFIG_NET_ESTIMATOR=y
+# CONFIG_NET_SCHED is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-
-#
-# Dongle support
-#
-CONFIG_DONGLE=y
-CONFIG_ESI_DONGLE=m
-CONFIG_ACTISYS_DONGLE=m
-CONFIG_TEKRAM_DONGLE=m
-# CONFIG_TOIM3232_DONGLE is not set
-CONFIG_LITELINK_DONGLE=m
-CONFIG_MA600_DONGLE=m
-CONFIG_GIRBIL_DONGLE=m
-CONFIG_MCP2120_DONGLE=m
-CONFIG_OLD_BELKIN_DONGLE=m
-CONFIG_ACT200L_DONGLE=m
-
-#
-# Old SIR device drivers
-#
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-# CONFIG_ALI_FIR is not set
-# CONFIG_VIA_FIR is not set
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIVHCI=m
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 # CONFIG_IEEE80211 is not set
-CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -504,7 +264,7 @@ CONFIG_WIRELESS_EXT=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
+# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 CONFIG_SYS_HYPERVISOR=y
 
@@ -530,14 +290,14 @@ CONFIG_SYS_HYPERVISOR=y
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
@@ -559,25 +319,24 @@ CONFIG_SCSI_PROC_FS=y
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=m
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
 
 #
 # SCSI Transport Attributes
 #
-CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
 
@@ -585,27 +344,13 @@ CONFIG_SCSI_FC_ATTRS=m
 # SCSI low-level drivers
 #
 # CONFIG_ISCSI_TCP is not set
-CONFIG_SCSI_SATA=m
+# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
 # Multi-device support (RAID and LVM)
 #
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID10=m
-# CONFIG_MD_RAID456 is not set
-CONFIG_MD_MULTIPATH=m
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_ZERO=m
-# CONFIG_DM_MULTIPATH is not set
+# CONFIG_MD is not set
 
 #
 # Fusion MPT device support
@@ -624,21 +369,19 @@ CONFIG_DM_ZERO=m
 # Network device support
 #
 CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # PHY device support
 #
-# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
+# CONFIG_NET_ETHERNET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -655,42 +398,18 @@ CONFIG_MII=m
 #
 # Wireless LAN (non-hamradio)
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_HOSTAP is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# ATM drivers
-#
-# CONFIG_ATM_DUMMY is not set
-CONFIG_ATM_TCP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPP_MPPE is not set
-CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
+# CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=m
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -920,9 +639,7 @@ CONFIG_DUMMY_CONSOLE=y
 # File systems
 #
 CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
@@ -933,33 +650,20 @@ CONFIG_FS_MBCACHE=y
 CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_JFS_FS=m
-CONFIG_JFS_POSIX_ACL=y
-# CONFIG_JFS_SECURITY is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_XFS_RT is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
-CONFIG_MINIX_FS=m
-CONFIG_ROMFS_FS=m
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
-CONFIG_QUOTA=y
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-CONFIG_QUOTACTL=y
+# CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
 
 #
@@ -969,8 +673,7 @@ CONFIG_JOLIET=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_ZISOFS_FS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
+# CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
@@ -979,7 +682,7 @@ CONFIG_MSDOS_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -997,61 +700,38 @@ CONFIG_RAMFS=y
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
 CONFIG_CRAMFS=y
-CONFIG_VXFS_FS=m
+# CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_QNX4FS_FS=m
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_UFS_DEBUG is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
 
 #
 # Network File Systems
 #
-CONFIG_NFS_FS=m
+CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
-CONFIG_LOCKD=m
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
-CONFIG_RPCSEC_GSS_SPKM3=m
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_WEAK_PW_HASH is not set
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-# CONFIG_CIFS_DEBUG2 is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_PACKET_SIGNING=y
-CONFIG_NCPFS_IOCTL_LOCKING=y
-CONFIG_NCPFS_STRONG=y
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_SMALLDOS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 # CONFIG_9P_FS is not set
@@ -1059,67 +739,52 @@ CONFIG_NCPFS_EXTRAS=y
 #
 # Partition Types
 #
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
+# CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_KARMA_PARTITION is not set
-CONFIG_EFI_PARTITION=y
 
 #
 # Native Language Support
 #
 CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Instrumentation Support
@@ -1135,7 +800,7 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
@@ -1170,29 +835,29 @@ CONFIG_FORCED_INLINING=y
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
 # CONFIG_CRYPTO_AES is not set
 # CONFIG_CRYPTO_AES_X86_64 is not set
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_ANUBIS is not set
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -1200,7 +865,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030206
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
 
 #
 # XEN
@@ -1210,8 +875,11 @@ CONFIG_XEN_PRIVCMD=y
 CONFIG_XEN_PRIVCMD=y
 CONFIG_XEN_XENBUS_DEV=y
 # CONFIG_XEN_BACKEND is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_GRANT_DEV=y
+# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
 CONFIG_XEN_SYSFS=y
@@ -1225,17 +893,13 @@ CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_SMPBOOT=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_DEVMEM=y
-# CONFIG_XEN_GRANT_DEV is not set
 
 #
 # Library routines
 #
-CONFIG_CRC_CCITT=m
+# CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
-CONFIG_CRC32=y
+# CONFIG_CRC32 is not set
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
 CONFIG_PLIST=y
diff -r 31d71546a644 -r 594bfb5cbe40 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32   Thu Feb 14 09:35:01 2008 -0700
+++ b/buildconfigs/linux-defconfig_xen_x86_32   Tue Feb 19 11:15:05 2008 -0700
@@ -1276,6 +1276,7 @@ CONFIG_I2O=m
 CONFIG_I2O=m
 CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
 CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
 CONFIG_I2O_CONFIG=m
 CONFIG_I2O_CONFIG_OLD_IOCTL=y
 CONFIG_I2O_BUS=m
@@ -1418,6 +1419,7 @@ CONFIG_S2IO=m
 CONFIG_S2IO=m
 CONFIG_S2IO_NAPI=y
 CONFIG_MYRI10GE=m
+# CONFIG_SFC is not set
 
 #
 # Token Ring devices
@@ -3249,7 +3251,7 @@ CONFIG_CRYPTO_TEST=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030206
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
 
 #
 # XEN
@@ -3263,6 +3265,8 @@ CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_NETDEV_BACKEND=y
 # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
 # CONFIG_XEN_NETDEV_LOOPBACK is not set
 CONFIG_XEN_PCIDEV_BACKEND=m
 CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
@@ -3273,8 +3277,9 @@ CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_GRANT_DEV=y
+# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
 CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_GRANT_DEV=y
 CONFIG_XEN_KEYBOARD=y
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
diff -r 31d71546a644 -r 594bfb5cbe40 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64   Thu Feb 14 09:35:01 2008 -0700
+++ b/buildconfigs/linux-defconfig_xen_x86_64   Tue Feb 19 11:15:05 2008 -0700
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18.8
-# Tue Oct 16 09:32:25 2007
+# Mon Feb 18 10:38:24 2008
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -1358,6 +1358,7 @@ CONFIG_S2IO=m
 CONFIG_S2IO=m
 CONFIG_S2IO_NAPI=y
 CONFIG_MYRI10GE=m
+# CONFIG_SFC is not set
 
 #
 # Token Ring devices
@@ -3080,7 +3081,7 @@ CONFIG_CRYPTO_TEST=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030206
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
 
 #
 # XEN
@@ -3094,6 +3095,8 @@ CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_BLKDEV_TAP=y
 CONFIG_XEN_NETDEV_BACKEND=y
 # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL is not set
+# CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND is not set
 # CONFIG_XEN_NETDEV_LOOPBACK is not set
 CONFIG_XEN_PCIDEV_BACKEND=m
 # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
@@ -3104,8 +3107,9 @@ CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_TPMDEV_BACKEND=m
 CONFIG_XEN_BLKDEV_FRONTEND=y
 CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_GRANT_DEV=y
+# CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND is not set
 CONFIG_XEN_FRAMEBUFFER=y
-CONFIG_XEN_GRANT_DEV=y
 CONFIG_XEN_KEYBOARD=y
 CONFIG_XEN_SCRUB_PAGES=y
 CONFIG_XEN_DISABLE_SERIAL=y
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/Kconfig
--- a/drivers/net/Kconfig       Thu Feb 14 09:35:01 2008 -0700
+++ b/drivers/net/Kconfig       Tue Feb 19 11:15:05 2008 -0700
@@ -2399,6 +2399,8 @@ config MYRI10GE
          <file:Documentation/networking/net-modules.txt>.  The module
          will be called myri10ge.
 
+source "drivers/net/sfc/Kconfig"
+
 endmenu
 
 source "drivers/net/tokenring/Kconfig"
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/Makefile
--- a/drivers/net/Makefile      Thu Feb 14 09:35:01 2008 -0700
+++ b/drivers/net/Makefile      Tue Feb 19 11:15:05 2008 -0700
@@ -219,3 +219,5 @@ obj-$(CONFIG_NETCONSOLE) += netconsole.o
 
 obj-$(CONFIG_FS_ENET) += fs_enet/
 
+obj-$(CONFIG_SFC) += sfc/
+
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/Kconfig
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/Kconfig   Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,35 @@
+config SFC
+       tristate "Solarflare Solarstorm SFC4000 support"
+       depends on PCI && INET
+       select MII
+       help
+         This driver supports 10-gigabit Ethernet cards based on
+         the Solarflare Communications Solarstorm SFC4000 controller.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called sfc.
+
+config SFC_DEBUGFS
+       bool "Solarflare Solarstorm SFC4000 debugging support"
+       depends on SFC && DEBUG_FS
+       default N
+       help
+         This option creates an "sfc" subdirectory of debugfs with
+         debugging information for the SFC4000 driver.
+
+         If unsure, say N.
+
+config SFC_MTD
+       depends on SFC && MTD && MTD_PARTITIONS
+       tristate "Solarflare Solarstorm SFC4000 flash/EEPROM support"
+       help
+         This module exposes the on-board flash and/or EEPROM memory as
+         MTD devices (e.g. /dev/mtd1).  This makes it possible to upload a
+         new boot ROM to the NIC.
+
+config SFC_RESOURCE
+       depends on SFC
+       tristate "Solarflare Solarstorm SFC4000 resource driver"
+       help
+         This module provides the SFC resource manager driver.
+
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/Makefile  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,43 @@
+
+# Final objects
+sfc_o = sfc.o
+sfc_mtd_o = sfc_mtd.o
+
+# Constituent objects
+sfc_elements_o :=
+sfc_elements_o += efx.o
+sfc_elements_o += falcon.o
+sfc_elements_o += tx.o
+sfc_elements_o += rx.o
+sfc_elements_o += mentormac.o
+sfc_elements_o += falcon_gmac.o
+sfc_elements_o += falcon_xmac.o
+sfc_elements_o += alaska.o
+sfc_elements_o += i2c-direct.o
+sfc_elements_o += selftest.o
+sfc_elements_o += driverlink.o
+ifeq ($(CONFIG_SFC_DEBUGFS),y)
+sfc_elements_o += debugfs.o
+endif
+sfc_elements_o += ethtool.o
+sfc_elements_o += xfp_phy.o
+sfc_elements_o += mdio_10g.o
+sfc_elements_o += txc43128_phy.o
+sfc_elements_o += tenxpress.o
+sfc_elements_o += lm87_support.o
+sfc_elements_o += boards.o
+sfc_elements_o += sfe4001.o
+sfc_elements_o += pm8358_phy.o
+sfc_elements_o += null_phy.o
+sfc_elements_o += phy.o
+sfc_elements_o += kernel_compat.o
+
+sfc_mtd_elements_o := mtd.o
+
+obj-$(CONFIG_SFC) += $(sfc_o)
+obj-$(CONFIG_SFC_MTD) += $(sfc_mtd_o)
+
+sfc-objs = $(sfc_elements_o)
+sfc_mtd-objs = $(sfc_mtd_elements_o)
+
+obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/alaska.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/alaska.c  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,159 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005:      Fen Systems Ltd.
+ * Copyright 2006-2007: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 "net_driver.h"
+#include <linux/ethtool.h>
+#include "gmii.h"
+#include "phy.h"
+
+/* Marvell 88E1111 "Alaska" PHY control */
+#define ALASKA_PHY_SPECIFIC 16
+#define ALASKA_ALLOW_SLEEP 0x0200
+
+#define ALASKA_EXTENDED_CONTROL 20
+#define EXTENDED_LINE_LOOPBACK 0x8000
+
+#define ALASKA_LED_CONTROL 24
+#define LED_BLINK_MASK 0x0700
+#define LED_BLINK_FAST 0x0100
+#define LED_BLINK_SLOW 0x0300
+#define LED_TX_CTRL_MASK 0x0041
+#define LED_TX_CTRL_LINK_AND_ACTIVITY 0x0001
+
+#define ALASKA_LED_OVERRIDE 25
+#define LED_LINK1000_MASK 0x0030
+#define LED_LINK1000_BLINK 0x0010
+#define LED_TX_MASK 0x0003
+#define LED_TX_BLINK 0x0001
+
+static void alaska_reconfigure(struct efx_nic *efx)
+{
+       struct mii_if_info *gmii = &efx->mii;
+       u32 bmcr, phy_ext;
+
+       /* Configure line loopback if requested */
+       phy_ext = gmii->mdio_read(gmii->dev, gmii->phy_id,
+                                 ALASKA_EXTENDED_CONTROL);
+       if (efx->loopback_mode == LOOPBACK_NETWORK)
+               phy_ext |= EXTENDED_LINE_LOOPBACK;
+       else
+               phy_ext &= ~EXTENDED_LINE_LOOPBACK;
+       gmii->mdio_write(gmii->dev, gmii->phy_id, ALASKA_EXTENDED_CONTROL,
+                        phy_ext);
+
+       /* Configure PHY loopback if requested */
+       bmcr = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_BMCR);
+       if (efx->loopback_mode == LOOPBACK_PHY)
+               bmcr |= BMCR_LOOPBACK;
+       else
+               bmcr &= ~BMCR_LOOPBACK;
+       gmii->mdio_write(gmii->dev, gmii->phy_id, MII_BMCR, bmcr);
+
+       /* Read link up status */
+       if (efx->loopback_mode == LOOPBACK_NONE)
+               efx->link_up = mii_link_ok(gmii);
+       else
+               efx->link_up = 1;
+
+       /* Determine link options from PHY */
+       if (gmii->force_media) {
+               efx->link_options = gmii_forced_result(bmcr);
+       } else {
+               int lpa = gmii_lpa(gmii);
+               int adv = gmii_advertised(gmii);
+               efx->link_options = gmii_nway_result(adv & lpa);
+       }
+}
+
+static void alaska_clear_interrupt(struct efx_nic *efx)
+{
+       struct mii_if_info *gmii = &efx->mii;
+
+       /* Read interrupt status register to clear */
+       gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_ISR);
+}
+
+static int alaska_init(struct efx_nic *efx)
+{
+       struct mii_if_info *gmii = &efx->mii;
+       u32 ier, leds, ctrl_1g, phy_spec;
+
+       /* Read ISR to clear any outstanding PHY interrupts */
+       gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_ISR);
+
+       /* Enable PHY interrupts */
+       ier = gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_IER);
+       ier |= IER_LINK_CHG;
+       gmii->mdio_write(gmii->dev, gmii->phy_id, GMII_IER, ier);
+
+       /* Remove 1G half-duplex as unsupported in Mentor MAC */
+       ctrl_1g = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000);
+       ctrl_1g &= ~(ADVERTISE_1000HALF);
+       gmii->mdio_write(gmii->dev, gmii->phy_id, MII_CTRL1000, ctrl_1g);
+
+       /*
+        * The PHY can save power when there is no external connection
+        * (sleep mode).  However, this is incompatible with PHY
+        * loopback, and if enable and disable it quickly the PHY can
+        * go to sleep even when sleep mode is disabled.  (SFC bug
+        * 9309.)  Therefore we disable it all the time.
+        */
+       phy_spec = gmii->mdio_read(gmii->dev, gmii->phy_id,
+                                  ALASKA_PHY_SPECIFIC);
+       phy_spec &= ~ALASKA_ALLOW_SLEEP;
+       gmii->mdio_write(gmii->dev, gmii->phy_id, ALASKA_PHY_SPECIFIC,
+                        phy_spec);
+
+       /* Configure LEDs */
+       leds = gmii->mdio_read(gmii->dev, gmii->phy_id, ALASKA_LED_CONTROL);
+       leds &= ~(LED_BLINK_MASK | LED_TX_CTRL_MASK);
+       leds |= (LED_BLINK_FAST | LED_TX_CTRL_LINK_AND_ACTIVITY);
+       gmii->mdio_write(gmii->dev, gmii->phy_id, ALASKA_LED_CONTROL, leds);
+
+       return 0;
+}
+
+static void alaska_fini(struct efx_nic *efx)
+{
+       struct mii_if_info *gmii = &efx->mii;
+       u32 ier;
+
+       /* Disable PHY interrupts */
+       ier = gmii->mdio_read(gmii->dev, gmii->phy_id, GMII_IER);
+       ier &= ~IER_LINK_CHG;
+       gmii->mdio_write(gmii->dev, gmii->phy_id, GMII_IER, ier);
+}
+
+
+struct efx_phy_operations alaska_phy_operations = {
+       .init            = alaska_init,
+       .fini            = alaska_fini,
+       .reconfigure     = alaska_reconfigure,
+       .clear_interrupt = alaska_clear_interrupt,
+       .loopbacks       = (1 << LOOPBACK_PHY) | (1 << LOOPBACK_NETWORK),
+       .startup_loopback = LOOPBACK_PHY,
+};
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/bitfield.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/bitfield.h        Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,544 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2006-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_BITFIELD_H
+#define EFX_BITFIELD_H
+
+/*
+ * Efx bitfield access
+ *
+ * Efx NICs make extensive use of bitfields up to 128 bits
+ * wide.  Since there is no native 128-bit datatype on most systems,
+ * and since 64-bit datatypes are inefficient on 32-bit systems and
+ * vice versa, we wrap accesses in a way that uses the most efficient
+ * datatype.
+ *
+ * The NICs are PCI devices and therefore little-endian.  Since most
+ * of the quantities that we deal with are DMAed to/from host memory,
+ * we define our datatypes (efx_oword_t, efx_qword_t and
+ * efx_dword_t) to be little-endian.
+ */
+
+/* Lowest bit numbers and widths */
+#define EFX_DUMMY_FIELD_LBN 0
+#define EFX_DUMMY_FIELD_WIDTH 0
+#define EFX_DWORD_0_LBN 0
+#define EFX_DWORD_0_WIDTH 32
+#define EFX_DWORD_1_LBN 32
+#define EFX_DWORD_1_WIDTH 32
+#define EFX_DWORD_2_LBN 64
+#define EFX_DWORD_2_WIDTH 32
+#define EFX_DWORD_3_LBN 96
+#define EFX_DWORD_3_WIDTH 32
+
+#define EFX_BYTE  1
+#define EFX_WORD  2
+#define EFX_DWORD 4
+#define EFX_OWORD 8
+
+/* Specified attribute (e.g. LBN) of the specified field */
+#define EFX_VAL(field, attribute) field ## _ ## attribute
+/* Low bit number of the specified field */
+#define EFX_LOW_BIT(field) EFX_VAL(field, LBN)
+/* Bit width of the specified field */
+#define EFX_WIDTH(field) EFX_VAL(field, WIDTH)
+/* High bit number of the specified field */
+#define EFX_HIGH_BIT(field) (EFX_LOW_BIT(field) + EFX_WIDTH(field) - 1)
+/* Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 64 bits.
+ */
+#define EFX_MASK64(field)                                      \
+       (EFX_WIDTH(field) == 64 ? ~((u64) 0) :          \
+        (((((u64) 1) << EFX_WIDTH(field))) - 1))
+
+/* Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 32 bits.  Use
+ * EFX_MASK64 for higher width fields.
+ */
+#define EFX_MASK32(field)                                      \
+       (EFX_WIDTH(field) == 32 ? ~((u32) 0) :          \
+        (((((u32) 1) << EFX_WIDTH(field))) - 1))
+
+/* A doubleword (i.e. 4 byte) datatype - little-endian in HW */
+typedef union efx_dword {
+       __le32 u32[1];
+} efx_dword_t;
+
+/* A quadword (i.e. 8 byte) datatype - little-endian in HW */
+typedef union efx_qword {
+       __le64 u64[1];
+       __le32 u32[2];
+       efx_dword_t dword[2];
+} efx_qword_t;
+
+/* An octword (eight-word, i.e. 16 byte) datatype - little-endian in HW */
+typedef union efx_oword {
+       __le64 u64[2];
+       efx_qword_t qword[2];
+       __le32 u32[4];
+       efx_dword_t dword[4];
+} efx_oword_t;
+
+/* Format string and value expanders for printk */
+#define EFX_DWORD_FMT "%08x"
+#define EFX_QWORD_FMT "%08x:%08x"
+#define EFX_OWORD_FMT "%08x:%08x:%08x:%08x"
+#define EFX_DWORD_VAL(dword)                           \
+       ((unsigned int) le32_to_cpu((dword).u32[0]))
+#define EFX_QWORD_VAL(qword)                           \
+       ((unsigned int) le32_to_cpu((qword).u32[1])),   \
+       ((unsigned int) le32_to_cpu((qword).u32[0]))
+#define EFX_OWORD_VAL(oword)                           \
+       ((unsigned int) le32_to_cpu((oword).u32[3])),   \
+       ((unsigned int) le32_to_cpu((oword).u32[2])),   \
+       ((unsigned int) le32_to_cpu((oword).u32[1])),   \
+       ((unsigned int) le32_to_cpu((oword).u32[0]))
+
+/*
+ * Extract bit field portion [low,high) from the native-endian element
+ * which contains bits [min,max).
+ *
+ * For example, suppose "element" represents the high 32 bits of a
+ * 64-bit value, and we wish to extract the bits belonging to the bit
+ * field occupying bits 28-45 of this 64-bit value.
+ *
+ * Then EFX_EXTRACT ( element, 32, 63, 28, 45 ) would give
+ *
+ *   ( element ) << 4
+ *
+ * The result will contain the relevant bits filled in in the range
+ * [0,high-low), with garbage in bits [high-low+1,...).
+ */
+#define EFX_EXTRACT_NATIVE(native_element, min, max, low, high)                
\
+       (((low > max) || (high < min)) ? 0 :                            \
+        ((low > min) ?                                                 \
+         ((native_element) >> (low - min)) :                           \
+         ((native_element) << (min - low))))
+
+/*
+ * Extract bit field portion [low,high) from the 64-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EFX_EXTRACT64(element, min, max, low, high)                    \
+       EFX_EXTRACT_NATIVE(le64_to_cpu(element), min, max, low, high)
+
+/*
+ * Extract bit field portion [low,high) from the 32-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EFX_EXTRACT32(element, min, max, low, high)                    \
+       EFX_EXTRACT_NATIVE(le32_to_cpu(element), min, max, low, high)
+
+#define EFX_EXTRACT_OWORD64(oword, low, high)                          \
+       (EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) |              \
+        EFX_EXTRACT64((oword).u64[1], 64, 127, low, high))
+
+#define EFX_EXTRACT_QWORD64(qword, low, high)                          \
+       EFX_EXTRACT64((qword).u64[0], 0, 63, low, high)
+
+#define EFX_EXTRACT_OWORD32(oword, low, high)                          \
+       (EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) |              \
+        EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) |             \
+        EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) |             \
+        EFX_EXTRACT32((oword).u32[3], 96, 127, low, high))
+
+#define EFX_EXTRACT_QWORD32(qword, low, high)                          \
+       (EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) |              \
+        EFX_EXTRACT32((qword).u32[1], 32, 63, low, high))
+
+#define EFX_EXTRACT_DWORD(dword, low, high)                            \
+       EFX_EXTRACT32((dword).u32[0], 0, 31, low, high)
+
+#define EFX_OWORD_FIELD64(oword, field)                                        
\
+       (EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
+        & EFX_MASK64(field))
+
+#define EFX_QWORD_FIELD64(qword, field)                                        
\
+       (EFX_EXTRACT_QWORD64(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
+        & EFX_MASK64(field))
+
+#define EFX_OWORD_FIELD32(oword, field)                                        
\
+       (EFX_EXTRACT_OWORD32(oword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
+        & EFX_MASK32(field))
+
+#define EFX_QWORD_FIELD32(qword, field)                                        
\
+       (EFX_EXTRACT_QWORD32(qword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
+        & EFX_MASK32(field))
+
+#define EFX_DWORD_FIELD(dword, field)                                     \
+       (EFX_EXTRACT_DWORD(dword, EFX_LOW_BIT(field), EFX_HIGH_BIT(field)) \
+        & EFX_MASK32(field))
+
+#define EFX_OWORD_IS_ZERO64(oword)                                     \
+       (((oword).u64[0] | (oword).u64[1]) == (__force __le64) 0)
+
+#define EFX_QWORD_IS_ZERO64(qword)                                     \
+       (((qword).u64[0]) == (__force __le64) 0)
+
+#define EFX_OWORD_IS_ZERO32(oword)                                          \
+       (((oword).u32[0] | (oword).u32[1] | (oword).u32[2] | (oword).u32[3]) \
+        == (__force __le32) 0)
+
+#define EFX_QWORD_IS_ZERO32(qword)                                     \
+       (((qword).u32[0] | (qword).u32[1]) == (__force __le32) 0)
+
+#define EFX_DWORD_IS_ZERO(dword)                                       \
+       (((dword).u32[0]) == (__force __le32) 0)
+
+#define EFX_OWORD_IS_ALL_ONES64(oword)                                 \
+       (((oword).u64[0] & (oword).u64[1]) == ~((__force __le64) 0))
+
+#define EFX_QWORD_IS_ALL_ONES64(qword)                                 \
+       ((qword).u64[0] == ~((__force __le64) 0))
+
+#define EFX_OWORD_IS_ALL_ONES32(oword)                                 \
+       (((oword).u32[0] & (oword).u32[1] & (oword).u32[2] & (oword).u32[3]) \
+        == ~((__force __le32) 0))
+
+#define EFX_QWORD_IS_ALL_ONES32(qword)                                 \
+       (((qword).u32[0] & (qword).u32[1]) == ~((__force __le32) 0))
+
+#define EFX_DWORD_IS_ALL_ONES(dword)                                   \
+       ((dword).u32[0] == ~((__force __le32) 0))
+
+#if BITS_PER_LONG == 64
+#define EFX_OWORD_FIELD                EFX_OWORD_FIELD64
+#define EFX_QWORD_FIELD                EFX_QWORD_FIELD64
+#define EFX_OWORD_IS_ZERO      EFX_OWORD_IS_ZERO64
+#define EFX_QWORD_IS_ZERO      EFX_QWORD_IS_ZERO64
+#define EFX_OWORD_IS_ALL_ONES  EFX_OWORD_IS_ALL_ONES64
+#define EFX_QWORD_IS_ALL_ONES  EFX_QWORD_IS_ALL_ONES64
+#else
+#define EFX_OWORD_FIELD                EFX_OWORD_FIELD32
+#define EFX_QWORD_FIELD                EFX_QWORD_FIELD32
+#define EFX_OWORD_IS_ZERO      EFX_OWORD_IS_ZERO32
+#define EFX_QWORD_IS_ZERO      EFX_QWORD_IS_ZERO32
+#define EFX_OWORD_IS_ALL_ONES  EFX_OWORD_IS_ALL_ONES32
+#define EFX_QWORD_IS_ALL_ONES  EFX_QWORD_IS_ALL_ONES32
+#endif
+
+/*
+ * Construct bit field portion
+ *
+ * Creates the portion of the bit field [low,high) that lies within
+ * the range [min,max).
+ */
+#define EFX_INSERT_NATIVE64(min, max, low, high, value)                \
+       (((low > max) || (high < min)) ? 0 :                    \
+        ((low > min) ?                                         \
+         (((u64) (value)) << (low - min)) :            \
+         (((u64) (value)) >> (min - low))))
+
+#define EFX_INSERT_NATIVE32(min, max, low, high, value)                \
+       (((low > max) || (high < min)) ? 0 :                    \
+        ((low > min) ?                                         \
+         (((u32) (value)) << (low - min)) :            \
+         (((u32) (value)) >> (min - low))))
+
+#define EFX_INSERT_NATIVE(min, max, low, high, value)          \
+       ((((max - min) >= 32) || ((high - low) >= 32)) ?        \
+        EFX_INSERT_NATIVE64(min, max, low, high, value) :      \
+        EFX_INSERT_NATIVE32(min, max, low, high, value))
+
+/*
+ * Construct bit field portion
+ *
+ * Creates the portion of the named bit field that lies within the
+ * range [min,max).
+ */
+#define EFX_INSERT_FIELD_NATIVE(min, max, field, value)                \
+       EFX_INSERT_NATIVE(min, max, EFX_LOW_BIT(field),         \
+                         EFX_HIGH_BIT(field), value)
+
+/*
+ * Construct bit field
+ *
+ * Creates the portion of the named bit fields that lie within the
+ * range [min,max).
+ */
+#define EFX_INSERT_FIELDS_NATIVE(min, max,                             \
+                                field1, value1,                        \
+                                field2, value2,                        \
+                                field3, value3,                        \
+                                field4, value4,                        \
+                                field5, value5,                        \
+                                field6, value6,                        \
+                                field7, value7,                        \
+                                field8, value8,                        \
+                                field9, value9,                        \
+                                field10, value10)                      \
+       (EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field4, (value4)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field5, (value5)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field6, (value6)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field7, (value7)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field8, (value8)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field9, (value9)) |      \
+        EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10)))
+
+#define EFX_INSERT_FIELDS64(...)                               \
+       cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
+
+#define EFX_INSERT_FIELDS32(...)                               \
+       cpu_to_le32(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__))
+
+#define EFX_POPULATE_OWORD64(oword, ...) do {                          \
+       (oword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__);       \
+       (oword).u64[1] = EFX_INSERT_FIELDS64(64, 127, __VA_ARGS__);     \
+       } while (0)
+
+#define EFX_POPULATE_QWORD64(qword, ...) do {                          \
+       (qword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__);       \
+       } while (0)
+
+#define EFX_POPULATE_OWORD32(oword, ...) do {                          \
+       (oword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__);       \
+       (oword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__);      \
+       (oword).u32[2] = EFX_INSERT_FIELDS32(64, 95, __VA_ARGS__);      \
+       (oword).u32[3] = EFX_INSERT_FIELDS32(96, 127, __VA_ARGS__);     \
+       } while (0)
+
+#define EFX_POPULATE_QWORD32(qword, ...) do {                          \
+       (qword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__);       \
+       (qword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__);      \
+       } while (0)
+
+#define EFX_POPULATE_DWORD(dword, ...) do {                            \
+       (dword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__);       \
+       } while (0)
+
+#if BITS_PER_LONG == 64
+#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD64
+#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD64
+#else
+#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD32
+#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD32
+#endif
+
+/* Populate an octword field with various numbers of arguments */
+#define EFX_POPULATE_OWORD_10 EFX_POPULATE_OWORD
+#define EFX_POPULATE_OWORD_9(oword, ...) \
+       EFX_POPULATE_OWORD_10(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_8(oword, ...) \
+       EFX_POPULATE_OWORD_9(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_7(oword, ...) \
+       EFX_POPULATE_OWORD_8(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_6(oword, ...) \
+       EFX_POPULATE_OWORD_7(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_5(oword, ...) \
+       EFX_POPULATE_OWORD_6(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_4(oword, ...) \
+       EFX_POPULATE_OWORD_5(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_3(oword, ...) \
+       EFX_POPULATE_OWORD_4(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_2(oword, ...) \
+       EFX_POPULATE_OWORD_3(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_OWORD_1(oword, ...) \
+       EFX_POPULATE_OWORD_2(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_ZERO_OWORD(oword) \
+       EFX_POPULATE_OWORD_1(oword, EFX_DUMMY_FIELD, 0)
+#define EFX_SET_OWORD(oword) \
+       EFX_POPULATE_OWORD_4(oword, \
+                            EFX_DWORD_0, 0xffffffff, \
+                            EFX_DWORD_1, 0xffffffff, \
+                            EFX_DWORD_2, 0xffffffff, \
+                            EFX_DWORD_3, 0xffffffff)
+
+/* Populate a quadword field with various numbers of arguments */
+#define EFX_POPULATE_QWORD_10 EFX_POPULATE_QWORD
+#define EFX_POPULATE_QWORD_9(qword, ...) \
+       EFX_POPULATE_QWORD_10(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_8(qword, ...) \
+       EFX_POPULATE_QWORD_9(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_7(qword, ...) \
+       EFX_POPULATE_QWORD_8(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_6(qword, ...) \
+       EFX_POPULATE_QWORD_7(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_5(qword, ...) \
+       EFX_POPULATE_QWORD_6(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_4(qword, ...) \
+       EFX_POPULATE_QWORD_5(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_3(qword, ...) \
+       EFX_POPULATE_QWORD_4(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_2(qword, ...) \
+       EFX_POPULATE_QWORD_3(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_QWORD_1(qword, ...) \
+       EFX_POPULATE_QWORD_2(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_ZERO_QWORD(qword) \
+       EFX_POPULATE_QWORD_1(qword, EFX_DUMMY_FIELD, 0)
+#define EFX_SET_QWORD(qword) \
+       EFX_POPULATE_QWORD_2(qword, \
+                            EFX_DWORD_0, 0xffffffff, \
+                            EFX_DWORD_1, 0xffffffff)
+
+/* Populate a dword field with various numbers of arguments */
+#define EFX_POPULATE_DWORD_10 EFX_POPULATE_DWORD
+#define EFX_POPULATE_DWORD_9(dword, ...) \
+       EFX_POPULATE_DWORD_10(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_8(dword, ...) \
+       EFX_POPULATE_DWORD_9(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_7(dword, ...) \
+       EFX_POPULATE_DWORD_8(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_6(dword, ...) \
+       EFX_POPULATE_DWORD_7(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_5(dword, ...) \
+       EFX_POPULATE_DWORD_6(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_4(dword, ...) \
+       EFX_POPULATE_DWORD_5(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_3(dword, ...) \
+       EFX_POPULATE_DWORD_4(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_2(dword, ...) \
+       EFX_POPULATE_DWORD_3(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_POPULATE_DWORD_1(dword, ...) \
+       EFX_POPULATE_DWORD_2(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__)
+#define EFX_ZERO_DWORD(dword) \
+       EFX_POPULATE_DWORD_1(dword, EFX_DUMMY_FIELD, 0)
+#define EFX_SET_DWORD(dword) \
+       EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xffffffff)
+
+/*
+ * Modify a named field within an already-populated structure.  Used
+ * for read-modify-write operations.
+ *
+ */
+
+#define EFX_INVERT_OWORD(oword) do {           \
+       (oword).u64[0] = ~((oword).u64[0]);     \
+       (oword).u64[1] = ~((oword).u64[1]);     \
+       } while (0)
+
+#define EFX_INSERT_FIELD64(...)                                        \
+       cpu_to_le64(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
+
+#define EFX_INSERT_FIELD32(...)                                        \
+       cpu_to_le32(EFX_INSERT_FIELD_NATIVE(__VA_ARGS__))
+
+#define EFX_INPLACE_MASK64(min, max, field)                    \
+       EFX_INSERT_FIELD64(min, max, field, EFX_MASK64(field))
+
+#define EFX_INPLACE_MASK32(min, max, field)                    \
+       EFX_INSERT_FIELD32(min, max, field, EFX_MASK32(field))
+
+#define EFX_SET_OWORD_FIELD64(oword, field, value) do {                        
\
+       (oword).u64[0] = (((oword).u64[0]                               \
+                          & ~EFX_INPLACE_MASK64(0,  63, field))        \
+                         | EFX_INSERT_FIELD64(0,  63, field, value));  \
+       (oword).u64[1] = (((oword).u64[1]                               \
+                          & ~EFX_INPLACE_MASK64(64, 127, field))       \
+                         | EFX_INSERT_FIELD64(64, 127, field, value)); \
+       } while (0)
+
+#define EFX_SET_QWORD_FIELD64(qword, field, value) do {                        
\
+       (qword).u64[0] = (((qword).u64[0]                               \
+                          & ~EFX_INPLACE_MASK64(0, 63, field))         \
+                         | EFX_INSERT_FIELD64(0, 63, field, value));   \
+       } while (0)
+
+#define EFX_SET_OWORD_FIELD32(oword, field, value) do {                        
\
+       (oword).u32[0] = (((oword).u32[0]                               \
+                          & ~EFX_INPLACE_MASK32(0, 31, field))         \
+                         | EFX_INSERT_FIELD32(0, 31, field, value));   \
+       (oword).u32[1] = (((oword).u32[1]                               \
+                          & ~EFX_INPLACE_MASK32(32, 63, field))        \
+                         | EFX_INSERT_FIELD32(32, 63, field, value));  \
+       (oword).u32[2] = (((oword).u32[2]                               \
+                          & ~EFX_INPLACE_MASK32(64, 95, field))        \
+                         | EFX_INSERT_FIELD32(64, 95, field, value));  \
+       (oword).u32[3] = (((oword).u32[3]                               \
+                          & ~EFX_INPLACE_MASK32(96, 127, field))       \
+                         | EFX_INSERT_FIELD32(96, 127, field, value)); \
+       } while (0)
+
+#define EFX_SET_QWORD_FIELD32(qword, field, value) do {                        
\
+       (qword).u32[0] = (((qword).u32[0]                               \
+                          & ~EFX_INPLACE_MASK32(0, 31, field))         \
+                         | EFX_INSERT_FIELD32(0, 31, field, value));   \
+       (qword).u32[1] = (((qword).u32[1]                               \
+                          & ~EFX_INPLACE_MASK32(32, 63, field))        \
+                         | EFX_INSERT_FIELD32(32, 63, field, value));  \
+       } while (0)
+
+#define EFX_SET_DWORD_FIELD(dword, field, value) do {                  \
+       (dword).u32[0] = (((dword).u32[0]                               \
+                          & ~EFX_INPLACE_MASK32(0, 31, field))         \
+                         | EFX_INSERT_FIELD32(0, 31, field, value));   \
+       } while (0)
+
+#if BITS_PER_LONG == 64
+#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD64
+#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD64
+#else
+#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD32
+#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD32
+#endif
+
+#define EFX_SET_OWORD_FIELD_VER(efx, oword, field, value) do { \
+       if (FALCON_REV(efx) == FALCON_REV_B0) {                    \
+               EFX_SET_OWORD_FIELD((oword), field##_B0, (value)); \
+       } else { \
+               EFX_SET_OWORD_FIELD((oword), field##_A1, (value)); \
+       } \
+} while (0)
+
+#define EFX_QWORD_FIELD_VER(efx, qword, field) \
+       (FALCON_REV(efx) == FALCON_REV_B0 ?     \
+        EFX_QWORD_FIELD((qword), field##_B0) : \
+        EFX_QWORD_FIELD((qword), field##_A1))
+
+/* Used to avoid compiler warnings about shift range exceeding width
+ * of the data types when dma_addr_t is only 32 bits wide.
+ */
+#define DMA_ADDR_T_WIDTH       (8 * sizeof(dma_addr_t))
+#define EFX_DMA_TYPE_WIDTH(width) \
+       (((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH)
+#define EFX_DMA_MAX_MASK ((DMA_ADDR_T_WIDTH == 64) ? \
+                         ~((u64) 0) : ~((u32) 0))
+#define EFX_DMA_MASK(mask) ((mask) & EFX_DMA_MAX_MASK)
+
+/*
+ * Determine if a DMA address is over the 4GB threshold
+ *
+ * Defined in a slightly tortuous way to avoid compiler warnings.
+ */
+static inline int efx_is_over_4gb(dma_addr_t address)
+{
+       if (DMA_ADDR_T_WIDTH > 32)
+               return (((u64) address) >> 32) ? 1 : 0;
+       else
+               /* Can never be true */
+               return 0;
+}
+
+#endif /* EFX_BITFIELD_H */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/boards.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/boards.c  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,528 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2007:      Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Developed by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 "net_driver.h"
+#include "phy.h"
+#include "lm87_support.h"
+#include "boards.h"
+#include "efx.h"
+
+/* Macros for unpacking the board revision */
+/* The revision info is in host byte order. */
+#define BOARD_TYPE(_rev) (_rev >> 8)
+#define BOARD_MAJOR(_rev) ((_rev >> 4) & 0xf)
+#define BOARD_MINOR(_rev) (_rev & 0xf)
+
+/* Blink support. If the PHY has no auto-blink mode so we hang it off a timer 
*/
+#define BLINK_INTERVAL (HZ/2)
+
+static void blink_led_timer(unsigned long context)
+{
+       struct efx_nic *efx = (struct efx_nic *)context;
+       struct efx_blinker *bl = &efx->board_info.blinker;
+       efx->board_info.set_fault_led(efx, bl->state);
+       bl->state = !bl->state;
+       if (bl->resubmit) {
+               bl->timer.expires = jiffies + BLINK_INTERVAL;
+               add_timer(&bl->timer);
+       }
+}
+
+static void board_blink(struct efx_nic *efx, int blink)
+{
+       struct efx_blinker *blinker = &efx->board_info.blinker;
+
+       /* The rtnl mutex serialises all ethtool ioctls, so
+        * nothing special needs doing here. */
+       if (blink) {
+               blinker->resubmit = 1;
+               blinker->state = 0;
+               setup_timer(&blinker->timer, blink_led_timer,
+                           (unsigned long)efx);
+               blinker->timer.expires = jiffies + BLINK_INTERVAL;
+               add_timer(&blinker->timer);
+       } else {
+               blinker->resubmit = 0;
+               if (blinker->timer.function)
+                       del_timer_sync(&blinker->timer);
+               efx->board_info.set_fault_led(efx, 0);
+       }
+}
+
+
+struct sensor_conf {
+       const char *name;
+       const unsigned high;
+       const unsigned low;
+};
+
+#define NO_LIMIT       ((unsigned)-1)
+
+#define LM87_SENSOR_BYTES      (18)
+
+static int sensor_limits_to_bytes(const struct sensor_conf *limits,
+                                 int nlimits, u8 *bytes, int maxbytes)
+{
+       int i, nbytes;
+       nbytes = 0;
+       for (i = 0; i < nlimits; i++) {
+               bytes[nbytes++] = limits[i].high;
+               if (limits[i].low != NO_LIMIT)
+                       bytes[nbytes++] = limits[i].low;
+               /* We may have overrun by one at this point, but this test
+                * should only trigger in development drivers as the sizes
+                * are not dynamic. */
+               if (nbytes > maxbytes) {
+                       printk(KERN_ERR "%s: out of space!\n", __func__);
+                       break;
+               }
+       }
+       return nbytes;
+}
+
+/*****************************************************************************
+ * Support for the SFE4002
+ *
+ */
+/* LM87 configuration data for the sensor on the SFE4002 board */
+static const struct sensor_conf sfe4002_lm87_limits[] = {
+       {"1.8V line", 0x91, 0x83},      /* 2.5V sensor, scaled for 1.8V */
+       {"1.2V line", 0x5a, 0x51},      /* Vccp1 */
+       {"3.3V line", 0xca, 0xb6},
+       {"5V line", 0xc9, 0xb6},
+       {"12V line", 0xe0, 0xb0},
+       {"1V line", 0x4b, 0x44},        /* vccp2 */
+       {"Ext. temp.", 0x46, 0x0a},     /* ASIC temp. */
+       {"Int. temp.", 0x3c, 0x0a},     /* Board temp. */
+       {"1.66V line", 0xb2, NO_LIMIT}, /* AIN1 only takes 1 value */
+       {"1.5V line", 0xa1, NO_LIMIT}   /* AIN2 only takes 1 value */
+};
+
+static const int sfe4002_lm87_nlimits = ARRAY_SIZE(sfe4002_lm87_limits);
+
+static u16 sfe4002_lm87_irq_mask = EFX_LM87_NO_INTS;
+
+/* I2C ID of the onboard LM87 chip. This is board-specific as the bottom two
+ * bits are set by strap pins */
+#define SFE4002_LM87_I2C_ID (0x2e)
+
+/****************************************************************************/
+/* LED allocations. Note that on rev A0 boards the schematic and the reality
+ * differ: red and green are swapped. Below is the fixed (A1) layout (there
+ * are only 3 A0 boards in existence, so no real reason to make this
+ * conditional).
+ */
+#define SFE4002_FAULT_LED (2)  /* Red */
+#define SFE4002_RX_LED    (0)  /* Green */
+#define SFE4002_TX_LED    (1)  /* Amber */
+
+static int sfe4002_init_leds(struct efx_nic *efx)
+{
+       /* Set the TX and RX LEDs to reflect status and activity, and the
+        * fault LED off */
+       xfp_set_led(efx, SFE4002_TX_LED,
+                   QUAKE_LED_TXLINK | QUAKE_LED_LINK_ACTSTAT);
+       xfp_set_led(efx, SFE4002_RX_LED,
+                   QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACTSTAT);
+       xfp_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF);
+       efx->board_info.blinker.led_num = SFE4002_FAULT_LED;
+       return 0;
+}
+
+static void sfe4002_fault_led(struct efx_nic *efx, int state)
+{
+       xfp_set_led(efx, SFE4002_FAULT_LED, state ? QUAKE_LED_ON :
+                       QUAKE_LED_OFF);
+}
+
+static int sfe4002_sensor_meaning(struct efx_nic *efx, int limit_num,
+                                 unsigned val)
+{
+       const struct sensor_conf *lim = &sfe4002_lm87_limits[limit_num];
+       if (lim->low == NO_LIMIT)
+               EFX_ERR(efx, "%10s  0x%02x (nominal value 0x%02x)\n", lim->name,
+                       val, lim->high);
+       else
+               EFX_ERR(efx, "%10s  0x%02x (nominal range 0x%02x - 0x%02x)\n",
+                       lim->name, val, lim->high, lim->low);
+       return 1;
+}
+
+static int sfe4002_check_hw(struct efx_nic *efx)
+{
+       int rc;
+
+       /* A0 board rev. 4002s  report a temperature fault the whole time
+        * (bad sensor) so we mask it out. */
+       unsigned alarm_mask = (efx->board_info.minor > 0) ?
+               0 : ~EFX_LM87_ETMP_INT;
+
+       /* Check the sensor (NOP if not present). */
+       rc = efx_check_lm87(efx, alarm_mask);
+
+       /* We treat both lm87 interrupts and failure to talk to the lm87
+        * as problems (since failure will only be reported if we did
+        * find the sensor at probe time. */
+       if (rc)
+               EFX_ERR(efx, "sensor alert!\n");
+       return rc;
+}
+
+static int sfe4002_init(struct efx_nic *efx)
+{
+       u8 lm87_bytes[LM87_SENSOR_BYTES];
+       int nbytes;
+       int rc;
+
+       efx->board_info.monitor = sfe4002_check_hw;
+       efx->board_info.interpret_sensor = sfe4002_sensor_meaning;
+       efx->board_info.init_leds = sfe4002_init_leds;
+       efx->board_info.set_fault_led = sfe4002_fault_led;
+       efx->board_info.blink = board_blink;
+       /* To clean up shut down the lm87 (NOP if not present) */
+       efx->board_info.fini = efx_remove_lm87;
+
+       nbytes = sensor_limits_to_bytes(sfe4002_lm87_limits,
+                                       sfe4002_lm87_nlimits, lm87_bytes,
+                                       LM87_SENSOR_BYTES);
+
+       /* Activate the lm87 sensor if present (succeeds if nothing there) */
+       rc = efx_probe_lm87(efx, SFE4002_LM87_I2C_ID,
+                           lm87_bytes, nbytes, sfe4002_lm87_irq_mask);
+
+       return rc;
+}
+
+/*****************************************************************************
+ * Support for the SFE4003
+ *
+ */
+/* LM87 configuration data for the sensor on the SFE4003 board */
+static const struct sensor_conf sfe4003_lm87_limits[] = {
+       {"1.5V line", 0x78, 0x6d},      /* 2.5V input, values scaled for 1.5V */
+       {"1.2V line", 0x5a, 0x51},      /* Vccp1 */
+       {"3.3V line", 0xca, 0xb6},
+       {"5V line", 0xc0, 0x00},        /* Sensor not connected. */
+       {"12V line", 0xe0, 0xb0},
+       {"1V line", 0x4b, 0x44},        /* Vccp2 */
+       {"Ext. temp.", 0x46, 0x0a},     /* ASIC temp. */
+       {"Int. temp.", 0x3c, 0x0a},     /* Board temp. */
+       {"", 0xff, NO_LIMIT},           /* FAN1/AIN1 unused */
+       {"", 0xff, NO_LIMIT}            /* FAN2/AIN2 unused */
+};
+
+static const int sfe4003_lm87_nlimits = ARRAY_SIZE(sfe4003_lm87_limits);
+
+static u16 sfe4003_lm87_irq_mask = EFX_LM87_NO_INTS;
+
+
+static int sfe4003_sensor_meaning(struct efx_nic *efx, int limit_num,
+                                 unsigned val)
+{
+       const struct sensor_conf *lim = &sfe4003_lm87_limits[limit_num];
+       if (lim->low == NO_LIMIT)
+               return 0; /* Neither AIN1 nor AIN2 mean anything to us */
+       else
+               EFX_ERR(efx, "%10s  0x%02x (nominal range 0x%02x - 0x%02x)\n",
+                       lim->name, val, lim->high, lim->low);
+       return 1;
+}
+
+/* I2C ID of the onboard LM87 chip. This is board-specific as the bottom two
+ * bits are set by strap pins */
+#define SFE4003_LM87_I2C_ID (0x2e)
+
+/* Board-specific LED info. */
+#define SFE4003_RED_LED_GPIO   (11)
+#define SFE4003_LED_ON         (1)
+#define SFE4003_LED_OFF                (0)
+
+static void sfe4003_fault_led(struct efx_nic *efx, int state)
+{
+       /* The LEDs were not wired to GPIOs before A3 */
+       if (efx->board_info.minor < 3 && efx->board_info.major == 0)
+               return;
+
+       txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO,
+                        state ? SFE4003_LED_ON : SFE4003_LED_OFF);
+}
+
+static int sfe4003_init_leds(struct efx_nic *efx)
+{
+       /* The LEDs were not wired to GPIOs before A3 */
+       if (efx->board_info.minor < 3 && efx->board_info.major == 0)
+               return 0;
+
+       txc_set_gpio_dir(efx, SFE4003_RED_LED_GPIO, TXC_GPIO_DIR_OUTPUT);
+       txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF);
+       return 0;
+}
+
+static int sfe4003_check_hw(struct efx_nic *efx)
+{
+       int rc;
+       /* A0/A1/A2 board rev. 4003s  report a temperature fault the whole time
+        * (bad sensor) so we mask it out. */
+       unsigned alarm_mask =
+               ~(EFX_LM87_ETMP_INT | EFX_LM87_FAN1_INT | EFX_LM87_FAN2_INT);
+
+       /* Check the sensor (NOP if not present). */
+
+       rc = efx_check_lm87(efx, alarm_mask);
+       /* We treat both lm87 interrupts and failure to talk to the lm87
+        * as problems (since failure will only be reported if we did
+        * find the sensor at probe time. */
+       if (rc)
+               EFX_ERR(efx, "sensor alert!\n");
+
+       return rc;
+}
+
+static int sfe4003_init(struct efx_nic *efx)
+{
+       u8 lm87_bytes[LM87_SENSOR_BYTES];
+       int nbytes;
+       int rc;
+       efx->board_info.monitor = sfe4003_check_hw;
+       efx->board_info.interpret_sensor = sfe4003_sensor_meaning;
+       efx->board_info.init_leds = sfe4003_init_leds;
+       efx->board_info.set_fault_led = sfe4003_fault_led;
+       efx->board_info.blink = board_blink;
+       /* To clean up shut down the lm87 (NOP if not present) */
+       efx->board_info.fini = efx_remove_lm87;
+
+       nbytes = sensor_limits_to_bytes(sfe4003_lm87_limits,
+                                       sfe4003_lm87_nlimits, lm87_bytes,
+                                       LM87_SENSOR_BYTES);
+
+       /* Activate the lm87 sensor if present (succeeds if nothing there) */
+       rc = efx_probe_lm87(efx, SFE4003_LM87_I2C_ID,
+                           lm87_bytes, nbytes, sfe4003_lm87_irq_mask);
+
+       if (rc < 0)
+               EFX_ERR(efx, "Temperature sensor probe failure: "
+                       "please check the jumper position\n");
+       return rc;
+}
+
+/*****************************************************************************
+ * Support for the SFE4005
+ *
+ */
+/* LM87 configuration data for the sensor on the SFE4005 board */
+static const u8 sfe4005_lm87_limits[] = {
+       0x51, /* 2.5V high lim. (actually monitor 1.0V line, so 1050mV)  */
+       0x49, /* 2.5V low lim. (950mV) */
+       0xf6, /* Vccp1 high lim. (3.3V rail, 3465 mV) */
+       0xde, /* Vcpp1 low lim. (3.3V rail, 3135 mV) */
+       0xca, /* 3.3V AUX high lim. (3465 mV)  */
+       0xb6, /* 3.3V AUX low lim. (3135mV) */
+       0xc0, /* 5V high lim. not connected) */
+       0x00, /* 5V low lim. (not connected) */
+       0xd0, /* 12V high lim. (13000mV) */
+       0xb0, /* 12V low lim. (11000mV) */
+       0xc0, /* Vccp2 high lim. (unused) */
+       0x00, /* Vccp2 low lim. (unused) */
+       0x46, /* Ext temp 1 (ASIC) high lim. */
+       0x0a, /* Ext temp 1 low lim. */
+       0x3c, /* Int temp (board) high lim. */
+       0x0a, /* Int temp 1 low lim. */
+       0xff, /* Fan 1 high (unused) */
+       0xff, /* Fan 2 high (unused) */
+};
+
+#define SFE4005_LM87_I2C_ID (0x2e)
+
+/* Until the LM87 monitoring is interrupt driven. */
+#define SFE4005_LM87_IRQMASK   EFX_LM87_NO_INTS
+
+#define SFE4005_PCF8575_I2C_ID (0x20)
+/* Definitions for the I/O expander that controls the CX4 chip:
+ * which PCF8575 pin maps to which function */
+#define SFE4005_PORT0_EXTLOOP  (1 << 0)
+#define SFE4005_PORT1_EXTLOOP  (1 << 1)
+#define SFE4005_HOSTPROT_LOOP  (1 << 2)
+#define SFE4005_BCAST          (1 << 3) /* TX on both ports */
+#define SFE4005_PORT0_EQ       (1 << 4)
+#define SFE4005_PORT1_EQ       (1 << 5)
+#define SFE4005_HOSTPORT_EQ    (1 << 6)
+#define        SFE4005_PORTSEL         (1 << 7) /* Which port (for RX in BCAST 
mode) */
+#define SFE4005_PORT0_PRE_LBN  (8)      /* Preemphasis on port 0 (2 bits)*/
+#define SFE4005_PORT1_PRE_LBN  (10)     /* Preemphasis on port 1 (2 bits)*/
+#define SFE4005_HOSTPORT_PRE_LBN (12)    /* Preemphasis on host port (2 bits) 
*/
+#define SFE4005_UNUSED         (1 << 14)
+#define SFE4005_CX4uC_nRESET   (1 << 15) /* Reset the controller on CX4 chip */
+
+
+/* By default only turn on host port EQ. Can also OR in SFE4005_PORT0_EQ,
+ * SFE4005_PORT1_EQ but this hasn't been seen to make a difference. */
+#define SFE4005_CX4_DEFAULTS (SFE4005_CX4uC_nRESET | SFE4005_HOSTPORT_EQ)
+
+static int sfe4005_write_ioexpander(struct efx_nic *efx)
+{
+       unsigned long iobits = (unsigned long)efx->phy_data;
+       struct efx_i2c_interface *i2c = &efx->i2c;
+       u8 send[2], check[2];
+       int rc;
+       /* Do not, EVER, deassert nRESET as that will reset Falcon too,
+        * and the driver won't know to repush the configuration, so
+        * nothing will work until the next power cycle. */
+       BUG_ON(!(iobits & SFE4005_CX4uC_nRESET));
+       send[0] = (iobits & 0xff);
+       send[1] = ((iobits >> 8) & 0xff);
+       rc = efx_i2c_send_bytes(i2c, SFE4005_PCF8575_I2C_ID, send, 2);
+       if (rc) {
+               EFX_ERR(efx, "failed to write to I/O expander: %d\n", rc);
+               return rc;
+       }
+       /* Paranoia: just check what the I/O expander reads back */
+       rc = efx_i2c_recv_bytes(i2c, SFE4005_PCF8575_I2C_ID, check, 2);
+       if (rc)
+               EFX_ERR(efx, "failed to read back from I/O expander: %d\n", rc);
+       else if (check[0] != send[0] || check[1] != send[1])
+               EFX_ERR(efx, "read back wrong value from I/O expander: "
+                       "wanted %.2x%.2x, got %.2x%.2x\n",
+                       send[1], send[0], check[1], check[0]);
+       return rc;
+}
+
+static int sfe4005_init(struct efx_nic *efx)
+{
+       unsigned long iobits = SFE4005_CX4_DEFAULTS;
+       int rc;
+
+       /* There is no PHY as such on the SFE4005 so phy_data is ours. */
+       efx->phy_data = (void *)iobits;
+
+       /* Push the values */
+       rc = sfe4005_write_ioexpander(efx);
+       if (rc)
+               return rc;
+
+       /* Activate the lm87 sensor if present (succeeds if nothing there) */
+       rc = efx_probe_lm87(efx, SFE4005_LM87_I2C_ID,
+                           sfe4005_lm87_limits,
+                           sizeof(sfe4005_lm87_limits), SFE4005_LM87_IRQMASK);
+
+       /* To clean up shut down the lm87 (NOP if not present) */
+       efx->board_info.fini = efx_remove_lm87;
+
+       return rc;
+}
+
+/* This will get expanded as board-specific details get moved out of the
+ * PHY drivers. */
+struct efx_board_data {
+       const char *ref_model;
+       const char *gen_type;
+       int (*init) (struct efx_nic *nic);
+       unsigned mwatts;
+};
+
+static void dummy_fini(struct efx_nic *nic)
+{
+}
+
+static int dummy_init(struct efx_nic *nic)
+{
+       nic->board_info.fini = dummy_fini;
+       return 0;
+}
+
+/* Maximum board power (mW)
+ * Falcon controller ASIC accounts for 2.2W
+ * 10Xpress PHY accounts for 12W
+ *
+ */
+#define SFE4001_POWER 18000
+#define SFE4002_POWER 7500
+#define SFE4003_POWER 4500
+#define SFE4005_POWER 4500
+
+static struct efx_board_data board_data[] = {
+       [EFX_BOARD_INVALID] =
+       {NULL,      NULL,                  dummy_init,      0},
+       [EFX_BOARD_SFE4001] =
+       {"SFE4001", "10GBASE-T adapter",   sfe4001_poweron, SFE4001_POWER },
+       [EFX_BOARD_SFE4002] =
+       {"SFE4002", "XFP adapter",         sfe4002_init,    SFE4002_POWER },
+       [EFX_BOARD_SFE4003] =
+       {"SFE4003", "10GBASE-CX4 adapter", sfe4003_init,    SFE4003_POWER },
+       [EFX_BOARD_SFE4005] =
+       {"SFE4005", "10G blade adapter",   sfe4005_init,    SFE4005_POWER },
+};
+
+int efx_set_board_info(struct efx_nic *efx, u16 revision_info)
+{
+       int rc = 0;
+       struct efx_board_data *data;
+
+       if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) {
+               EFX_ERR(efx, "squashing unknown board type %d\n",
+                       BOARD_TYPE(revision_info));
+               revision_info = 0;
+       }
+
+       if (BOARD_TYPE(revision_info) == 0) {
+               efx->board_info.major = 0;
+               efx->board_info.minor = 0;
+               /* For early boards that don't have revision info. there is
+                * only 1 board for each PHY type, so we can work it out, with
+                * the exception of the PHY-less boards. */
+               switch (efx->phy_type) {
+               case PHY_TYPE_10XPRESS:
+                       efx->board_info.type = EFX_BOARD_SFE4001;
+                       break;
+               case PHY_TYPE_XFP:
+                       efx->board_info.type = EFX_BOARD_SFE4002;
+                       break;
+               case PHY_TYPE_CX4_RTMR:
+                       efx->board_info.type = EFX_BOARD_SFE4003;
+                       break;
+               default:
+                       efx->board_info.type = 0;
+                       break;
+               }
+       } else {
+               efx->board_info.type = BOARD_TYPE(revision_info);
+               efx->board_info.major = BOARD_MAJOR(revision_info);
+               efx->board_info.minor = BOARD_MINOR(revision_info);
+       }
+
+       data = &board_data[efx->board_info.type];
+
+       /* Report the board model number or generic type for recognisable
+        * boards. */
+       if (efx->board_info.type != 0)
+               EFX_INFO(efx, "board is %s rev %c%d\n",
+                        (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
+                        ? data->ref_model : data->gen_type,
+                        'A' + efx->board_info.major, efx->board_info.minor);
+
+       efx->board_info.init = data->init;
+       efx->board_info.mwatts = data->mwatts;
+
+       return rc;
+}
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/boards.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/boards.h  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,51 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2007:      Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Developed by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_BOARDS_H
+#define EFX_BOARDS_H
+
+/* Board IDs (must fit in 8 bits). Note that 0 must never be assigned because
+ * on early boards it means there is no revision info. Board types pre 400x
+ * are not covered here, but this is not a problem because:
+ * - the early Falcon boards (FPGA, 401, 403) don't have any extra H/W we
+ * need care about and aren't being updated.
+ */
+enum efx_board_type {
+       EFX_BOARD_INVALID = 0, /* Early boards do not have board rev. info. */
+       EFX_BOARD_SFE4001 = 1,
+       EFX_BOARD_SFE4002 = 2,
+       EFX_BOARD_SFE4003 = 3,
+       EFX_BOARD_SFE4005 = 4,
+       /* Insert new types before here */
+       EFX_BOARD_MAX
+};
+
+extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info);
+
+/* SFE4001 (10GBASE-T) */
+extern int sfe4001_poweron(struct efx_nic *efx);
+extern void sfe4001_poweroff(struct efx_nic *efx);
+
+#endif
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/config.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/config.h  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,1 @@
+/* SFC config options can go here */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/debugfs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/debugfs.c Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,924 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2006-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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/module.h>
+#include <linux/pci.h>
+/* For out-of-tree builds we always need procfs, if only for a compatibility
+ * symlink.
+ */
+#include <linux/proc_fs.h>
+#include <linux/dcache.h>
+#include <linux/seq_file.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "debugfs.h"
+#include "falcon.h"
+
+/* EFX_USE_DEBUGFS is defined by kernel_compat.h so we can't decide whether to
+ * include this earlier.
+ */
+#ifdef EFX_USE_DEBUGFS
+#include <linux/debugfs.h>
+#endif
+
+#ifndef PRIu64
+#      if (BITS_PER_LONG == 64)
+#              define PRIu64 "lu"
+#      else
+#              define PRIu64 "llu"
+#      endif
+#endif
+
+#ifndef EFX_USE_DEBUGFS
+
+static void efx_debugfs_remove(struct proc_dir_entry *entry)
+{
+       if (entry)
+               remove_proc_entry(entry->name, entry->parent);
+}
+#define debugfs_remove efx_debugfs_remove
+
+#define debugfs_create_dir proc_mkdir
+#define debugfs_create_symlink proc_symlink
+
+#endif /* !EFX_USE_DEBUGFS */
+
+/* Parameter definition bound to a structure - each file has one of these */
+struct efx_debugfs_bound_param {
+       const struct efx_debugfs_parameter *param;
+       void *structure;
+};
+
+
+/* Maximum length for a name component or symlink target */
+#define EFX_DEBUGFS_NAME_LEN 32
+
+
+/* Top-level debug directory ([/sys/kernel]/debug/sfc) */
+static struct dentry *efx_debug_root;
+
+/* "cards" directory ([/sys/kernel]/debug/sfc/cards) */
+static struct dentry *efx_debug_cards;
+
+
+/* Sequential file interface to bound parameters */
+
+#if defined(EFX_USE_DEBUGFS)
+
+static int efx_debugfs_seq_show(struct seq_file *file, void *v)
+{
+       struct efx_debugfs_bound_param *binding =
+               (struct efx_debugfs_bound_param *)file->private;
+
+       return binding->param->reader(file,
+                                     binding->structure +
+                                     binding->param->offset);
+}
+
+static int efx_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, efx_debugfs_seq_show, inode->i_private);
+}
+
+#else /* EFX_NOT_UPSTREAM && !EFX_USE_DEBUGFS */
+
+static int efx_debugfs_seq_show(struct seq_file *file, void *v)
+{
+       struct proc_dir_entry *entry = (struct proc_dir_entry *)file->private;
+       struct efx_debugfs_parameter *param =
+               (struct efx_debugfs_parameter *)entry->data;
+       void *structure = (void *)entry->read_proc;
+
+       if (!structure)
+               return -EIO;
+
+       return param->reader(file, structure + param->offset);
+}
+
+static int efx_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, efx_debugfs_seq_show, PROC_I(inode)->pde);
+}
+
+#endif /* !EFX_NOT_UPSTREAM || EFX_USE_DEBUGFS */
+
+
+static struct file_operations efx_debugfs_file_ops = {
+       .owner   = THIS_MODULE,
+       .open    = efx_debugfs_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+
+#if defined(EFX_USE_DEBUGFS)
+
+/**
+ * efx_fini_debugfs_child - remove a named child of a debugfs directory
+ * @dir:               Directory
+ * @name:              Name of child
+ *
+ * This removes the named child from the directory, if it exists.
+ */
+void efx_fini_debugfs_child(struct dentry *dir, const char *name)
+{
+       struct qstr child_name;
+       struct dentry *child;
+
+       child_name.len = strlen(name);
+       child_name.name = name;
+       child_name.hash = full_name_hash(child_name.name, child_name.len);
+       child = d_lookup(dir, &child_name);
+       if (child) {
+               /* If it's a "regular" file, free its parameter binding */
+               if (S_ISREG(child->d_inode->i_mode))
+                       kfree(child->d_inode->i_private);
+               debugfs_remove(child);
+               dput(child);
+       }
+}
+
+#else /* EFX_NOT_UPSTREAM && !EFX_USE_DEBUGFS */
+
+void efx_fini_debugfs_child(struct proc_dir_entry *dir, const char *name)
+{
+       remove_proc_entry(name, dir);
+}
+
+#endif /* !EFX_NOT_UPSTREAM || EFX_USE_DEBUGFS */
+
+/*
+ * Remove a debugfs directory.
+ *
+ * This removes the named parameter-files and sym-links from the
+ * directory, and the directory itself.  It does not do any recursion
+ * to subdirectories.
+ */
+static void efx_fini_debugfs_dir(struct dentry *dir,
+                                struct efx_debugfs_parameter *params,
+                                const char *const *symlink_names)
+{
+       if (!dir)
+               return;
+
+       while (params->name) {
+               efx_fini_debugfs_child(dir, params->name);
+               params++;
+       }
+       while (symlink_names && *symlink_names) {
+               efx_fini_debugfs_child(dir, *symlink_names);
+               symlink_names++;
+       }
+       debugfs_remove(dir);
+}
+
+/* Functions for printing various types of parameter. */
+
+int efx_debugfs_read_uint(struct seq_file *file, void *data)
+{
+       return seq_printf(file, "%#x\n", *(unsigned int *)data);
+}
+
+int efx_debugfs_read_int(struct seq_file *file, void *data)
+{
+       return seq_printf(file, "%d\n", *(int *)data);
+}
+
+int efx_debugfs_read_atomic(struct seq_file *file, void *data)
+{
+       unsigned int value = atomic_read((atomic_t *) data);
+
+       return seq_printf(file, "%#x\n", value);
+}
+
+int efx_debugfs_read_dword(struct seq_file *file, void *data)
+{
+       unsigned int value = EFX_DWORD_FIELD(*(efx_dword_t *) data,
+                                            EFX_DWORD_0);
+
+       return seq_printf(file, "%#x\n", value);
+}
+
+static int efx_debugfs_read_int_mode(struct seq_file *file, void *data)
+{
+       unsigned int value = *(enum efx_int_mode *) data;
+
+       return seq_printf(file, "%d => %s\n", value,
+                         STRING_TABLE_LOOKUP(value, efx_interrupt_mode));
+}
+
+#define EFX_INT_MODE_PARAMETER(container_type, parameter)              \
+       EFX_PARAMETER(container_type, parameter,                        \
+                     enum efx_int_mode, efx_debugfs_read_int_mode)
+
+static int efx_debugfs_read_loop_mode(struct seq_file *file, void *data)
+{
+       unsigned int value = *(enum efx_loopback_mode *)data;
+
+       return seq_printf(file, "%d => %s\n", value,
+                         STRING_TABLE_LOOKUP(value, efx_loopback_mode));
+}
+
+#define EFX_LOOPBACK_MODE_PARAMETER(container_type, parameter)         \
+       EFX_PARAMETER(container_type, parameter,                        \
+                     enum efx_loopback_mode, efx_debugfs_read_loop_mode)
+
+static int efx_debugfs_read_phy_type(struct seq_file *file, void *data)
+{
+       unsigned int value = *(enum phy_type *) data;
+
+       return seq_printf(file, "%d => %s\n", value,
+                         STRING_TABLE_LOOKUP(value, efx_phy_type));
+}
+
+#define EFX_PHY_TYPE_PARAMETER(container_type, parameter)              \
+       EFX_PARAMETER(container_type, parameter,                        \
+                     enum phy_type, efx_debugfs_read_phy_type)
+
+int efx_debugfs_read_string(struct seq_file *file, void *data)
+{
+       return seq_puts(file, (const char *)data);
+}
+
+
+/**
+ * efx_init_debugfs_files - create parameter-files in a debugfs directory
+ * @parent:            Containing directory
+ * @params:            Pointer to zero-terminated parameter definition array
+ * @structure:         Structure containing parameters
+ *
+ * Add parameter-files to the given debugfs directory.  Return a
+ * negative error code or 0 on success.
+ */
+static int efx_init_debugfs_files(struct dentry *parent,
+                                 struct efx_debugfs_parameter *params,
+                                 void *structure)
+{
+       struct efx_debugfs_parameter *param = params;
+
+       while (param->name) {
+               struct dentry *entry;
+#if defined(EFX_USE_DEBUGFS)
+               struct efx_debugfs_bound_param *binding;
+
+               binding = kmalloc(sizeof(*binding), GFP_KERNEL);
+               if (!binding)
+                       goto err;
+               binding->param = param;
+               binding->structure = structure;
+
+               entry = debugfs_create_file(param->name, S_IRUGO, parent,
+                                           binding, &efx_debugfs_file_ops);
+               if (!entry) {
+                       kfree(binding);
+                       goto err;
+               }
+#else
+               entry = create_proc_entry(param->name, S_IRUGO, parent);
+               if (!entry)
+                       goto err;
+               /*
+                * We have no good way to free a binding created here.
+                * However, once we install our file_operations the
+                * read_proc pointer becomes redundant and we can
+                * abuse it as a structure pointer.
+                */
+               entry->data = param;
+               entry->read_proc = NULL;
+               smp_wmb();
+               entry->proc_fops = &efx_debugfs_file_ops;
+               smp_wmb();
+               entry->read_proc = (read_proc_t *) structure;
+#endif
+
+               param++;
+       }
+
+       return 0;
+
+ err:
+       while (param != params) {
+               param--;
+               efx_fini_debugfs_child(parent, param->name);
+       }
+       return -ENOMEM;
+}
+
+/**
+ * efx_init_debugfs_netdev - create debugfs sym-links for net device
+ * @net_dev:           Net device
+ *
+ * Create sym-links named after @net_dev to the debugfs directories for
+ * the corresponding NIC and  port.  Return a negative error code or 0 on
+ * success.  The sym-links must be cleaned up using
+ * efx_fini_debugfs_netdev().
+ */
+int efx_init_debugfs_netdev(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+       char name[EFX_DEBUGFS_NAME_LEN];
+       char target[EFX_DEBUGFS_NAME_LEN];
+       size_t len;
+
+       if (snprintf(name, sizeof(name), "nic_%s", net_dev->name) >=
+           sizeof(name))
+               return -ENAMETOOLONG;
+       if (snprintf(target, sizeof(target), "cards/%s", pci_name(efx->pci_dev))
+           >= sizeof(target))
+               return -ENAMETOOLONG;
+       efx->debug_symlink = debugfs_create_symlink(name,
+                                                   efx_debug_root, target);
+       if (!efx->debug_symlink)
+               return -ENOMEM;
+
+       if (snprintf(name, sizeof(name), "if_%s", net_dev->name) >=
+           sizeof(name))
+               return -ENAMETOOLONG;
+       len = snprintf(target, sizeof(target),
+                      "cards/%s/port0", pci_name(efx->pci_dev));
+       if (len >= sizeof(target))
+               return -ENAMETOOLONG;
+       efx->debug_port_symlink = debugfs_create_symlink(name,
+                                                        efx_debug_root,
+                                                        target);
+       if (!efx->debug_port_symlink)
+               return -ENOMEM;
+
+       return 0;
+}
+
+/**
+ * efx_fini_debugfs_netdev - remove debugfs sym-links for net device
+ * @net_dev:           Net device
+ *
+ * Remove sym-links created for @net_dev by efx_init_debugfs_netdev().
+ */
+void efx_fini_debugfs_netdev(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       debugfs_remove(efx->debug_port_symlink);
+       efx->debug_port_symlink = NULL;
+       debugfs_remove(efx->debug_symlink);
+       efx->debug_symlink = NULL;
+}
+
+/* Per-port parameters */
+static struct efx_debugfs_parameter efx_debugfs_port_parameters[] = {
+       EFX_NAMED_PARAMETER(enabled, struct efx_nic, port_enabled,
+                           int, efx_debugfs_read_int),
+       EFX_INT_PARAMETER(struct efx_nic, net_dev_registered),
+       EFX_INT_PARAMETER(struct efx_nic, rx_checksum_enabled),
+       EFX_ATOMIC_PARAMETER(struct efx_nic, netif_stop_count),
+       EFX_INT_PARAMETER(struct efx_nic, link_up),
+       EFX_UINT_PARAMETER(struct efx_nic, link_options),
+       EFX_INT_PARAMETER(struct efx_nic, promiscuous),
+       EFX_UINT_PARAMETER(struct efx_nic, loopback_modes),
+       EFX_LOOPBACK_MODE_PARAMETER(struct efx_nic, loopback_mode),
+       EFX_PHY_TYPE_PARAMETER(struct efx_nic, phy_type),
+       EFX_NAMED_PARAMETER(phy_id, struct efx_nic, mii.phy_id,
+                           int, efx_debugfs_read_int),
+       EFX_UINT_PARAMETER(struct efx_nic, n_link_state_changes),
+       {NULL},
+};
+
+/**
+ * efx_init_debugfs_port - create debugfs directory for port
+ * @efx:               Efx NIC
+ *
+ * Create a debugfs directory containing parameter-files for @efx.
+ * Return a negative error code or 0 on success.  The directory must be
+ * cleaned up using efx_fini_debugfs_port().
+ */
+int efx_init_debugfs_port(struct efx_nic *efx)
+{
+       int rc;
+
+       /* Create directory */
+       efx->debug_port_dir = debugfs_create_dir("port0", efx->debug_dir);
+       if (!efx->debug_port_dir)
+               return -ENOMEM;
+
+       /* Create files */
+       rc = efx_init_debugfs_files(efx->debug_port_dir,
+                                   efx_debugfs_port_parameters,
+                                   (void *)efx);
+       if (rc)
+               efx_fini_debugfs_port(efx);
+
+       return rc;
+}
+
+/**
+ * efx_fini_debugfs_port - remove debugfs directory for port
+ * @efx:               Efx NIC
+ *
+ * Remove directory created for @efx by efx_init_debugfs_port().
+ */
+void efx_fini_debugfs_port(struct efx_nic *efx)
+{
+       efx_fini_debugfs_dir(efx->debug_port_dir,
+                            efx_debugfs_port_parameters, NULL);
+       efx->debug_port_dir = NULL;
+}
+
+/**
+ * efx_extend_debugfs_port - add parameter-files to directory for port
+ * @efx:               Efx NIC
+ * @structure:         Structure containing parameters
+ * @params:            Pointer to zero-terminated parameter definition array
+ *
+ * Add parameter-files to the debugfs directory for @efx.  Return
+ * a negative error code or 0 on success.  This is intended for
+ * PHY-specific parameters.  The files must be cleaned up using
+ * efx_trim_debugfs_port().
+ */
+int efx_extend_debugfs_port(struct efx_nic *efx,
+                           void *structure,
+                           struct efx_debugfs_parameter *params)
+{
+       return efx_init_debugfs_files(efx->debug_port_dir, params, structure);
+}
+
+/**
+ * efx_trim_debugfs_port - remove parameter-files from directory for port
+ * @efx:               Efx NIC
+ * @params:            Pointer to zero-terminated parameter definition array
+ *
+ * Remove parameter-files previously added to the debugfs directory
+ * for @efx using efx_extend_debugfs_port().
+ */
+void efx_trim_debugfs_port(struct efx_nic *efx,
+                          struct efx_debugfs_parameter *params)
+{
+       struct dentry *dir = efx->debug_port_dir;
+
+       if (dir) {
+               struct efx_debugfs_parameter *field;
+               for (field = params; field->name; field++)
+                       efx_fini_debugfs_child(dir, field->name);
+       }
+}
+
+/* Per-TX-queue parameters */
+static struct efx_debugfs_parameter efx_debugfs_tx_queue_parameters[] = {
+       EFX_UINT_PARAMETER(struct efx_tx_queue, insert_count),
+       EFX_UINT_PARAMETER(struct efx_tx_queue, write_count),
+       EFX_UINT_PARAMETER(struct efx_tx_queue, read_count),
+       EFX_INT_PARAMETER(struct efx_tx_queue, stopped),
+       {NULL},
+};
+
+static void efx_fini_debugfs_tx_queue(struct efx_tx_queue *tx_queue);
+
+/**
+ * efx_init_debugfs_tx_queue - create debugfs directory for TX queue
+ * @tx_queue:          Efx TX queue
+ *
+ * Create a debugfs directory containing parameter-files for @tx_queue.
+ * Return a negative error code or 0 on success.  The directory must be
+ * cleaned up using efx_fini_debugfs_tx_queue().
+ */
+static int efx_init_debugfs_tx_queue(struct efx_tx_queue *tx_queue)
+{
+       char name[EFX_DEBUGFS_NAME_LEN];
+       char target[EFX_DEBUGFS_NAME_LEN];
+       int rc;
+
+       /* Create directory */
+       if (snprintf(name, sizeof(name), EFX_TX_QUEUE_NAME(tx_queue))
+           >= sizeof(name))
+               goto err_len;
+       tx_queue->debug_dir = debugfs_create_dir(name,
+                                                tx_queue->efx->debug_dir);
+       if (!tx_queue->debug_dir)
+               goto err_mem;
+
+       /* Create files */
+       rc = efx_init_debugfs_files(tx_queue->debug_dir,
+                                   efx_debugfs_tx_queue_parameters,
+                                   (void *)tx_queue);
+       if (rc)
+               goto err;
+
+       /* Create symlink to channel */
+       if (snprintf(target, sizeof(target),
+                    "../" EFX_CHANNEL_NAME(tx_queue->channel)) >=
+           sizeof(target))
+               goto err_len;
+       if (!debugfs_create_symlink("channel", tx_queue->debug_dir, target))
+               goto err_mem;
+
+       /* Create symlink to port */
+       if (!debugfs_create_symlink("port", tx_queue->debug_dir, "../port0"))
+               goto err_mem;
+
+       return 0;
+
+ err_len:
+       rc = -ENAMETOOLONG;
+       goto err;
+ err_mem:
+       rc = -ENOMEM;
+ err:
+       efx_fini_debugfs_tx_queue(tx_queue);
+       return rc;
+}
+
+/**
+ * efx_fini_debugfs_tx_queue - remove debugfs directory for TX queue
+ * @tx_queue:          Efx TX queue
+ *
+ * Remove directory created for @tx_queue by efx_init_debugfs_tx_queue().
+ */
+static void efx_fini_debugfs_tx_queue(struct efx_tx_queue *tx_queue)
+{
+       static const char *const symlink_names[] = {
+               "channel", "port", NULL
+       };
+
+       efx_fini_debugfs_dir(tx_queue->debug_dir,
+                            efx_debugfs_tx_queue_parameters, symlink_names);
+       tx_queue->debug_dir = NULL;
+}
+
+/* Per-RX-queue parameters */
+static struct efx_debugfs_parameter efx_debugfs_rx_queue_parameters[] = {
+       EFX_INT_PARAMETER(struct efx_rx_queue, added_count),
+       EFX_INT_PARAMETER(struct efx_rx_queue, removed_count),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, max_fill),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, fast_fill_trigger),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, fast_fill_limit),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, min_fill),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, min_overfill),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, alloc_page_count),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, alloc_skb_count),
+       EFX_UINT_PARAMETER(struct efx_rx_queue, slow_fill_count),
+       {NULL},
+};
+
+static void efx_fini_debugfs_rx_queue(struct efx_rx_queue *rx_queue);
+
+/**
+ * efx_init_debugfs_rx_queue - create debugfs directory for RX queue
+ * @rx_queue:          Efx RX queue
+ *
+ * Create a debugfs directory containing parameter-files for @rx_queue.
+ * Return a negative error code or 0 on success.  The directory must be
+ * cleaned up using efx_fini_debugfs_rx_queue().
+ */
+static int efx_init_debugfs_rx_queue(struct efx_rx_queue *rx_queue)
+{
+       char name[EFX_DEBUGFS_NAME_LEN];
+       char target[EFX_DEBUGFS_NAME_LEN];
+       int rc;
+
+       /* Create directory */
+       if (snprintf(name, sizeof(name), EFX_RX_QUEUE_NAME(rx_queue))
+           >= sizeof(name))
+               goto err_len;
+       rx_queue->debug_dir = debugfs_create_dir(name,
+                                                rx_queue->efx->debug_dir);
+       if (!rx_queue->debug_dir)
+               goto err_mem;
+
+       /* Create files */
+       rc = efx_init_debugfs_files(rx_queue->debug_dir,
+                                   efx_debugfs_rx_queue_parameters,
+                                   (void *)rx_queue);
+       if (rc)
+               goto err;
+
+       /* Create symlink to channel */
+       if (snprintf(target, sizeof(target),
+                    "../" EFX_CHANNEL_NAME(rx_queue->channel)) >=
+           sizeof(target))
+               goto err_len;
+       if (!debugfs_create_symlink("channel", rx_queue->debug_dir, target))
+               goto err_mem;
+
+       return 0;
+
+ err_len:
+       rc = -ENAMETOOLONG;
+       goto err;
+ err_mem:
+       rc = -ENOMEM;
+ err:
+       efx_fini_debugfs_rx_queue(rx_queue);
+       return rc;
+}
+
+/**
+ * efx_fini_debugfs_rx_queue - remove debugfs directory for RX queue
+ * @rx_queue:          Efx RX queue
+ *
+ * Remove directory created for @rx_queue by efx_init_debugfs_rx_queue().
+ */
+static void efx_fini_debugfs_rx_queue(struct efx_rx_queue *rx_queue)
+{
+       const char *const symlink_names[] = {
+               "channel", NULL
+       };
+
+       efx_fini_debugfs_dir(rx_queue->debug_dir,
+                            efx_debugfs_rx_queue_parameters, symlink_names);
+       rx_queue->debug_dir = NULL;
+}
+
+/* Per-channel parameters */
+static struct efx_debugfs_parameter efx_debugfs_channel_parameters[] = {
+       EFX_INT_PARAMETER(struct efx_channel, enabled),
+       EFX_INT_PARAMETER(struct efx_channel, irq),
+       EFX_UINT_PARAMETER(struct efx_channel, has_interrupt),
+       EFX_UINT_PARAMETER(struct efx_channel, irq_moderation),
+       EFX_UINT_PARAMETER(struct efx_channel, eventq_read_ptr),
+       EFX_UINT_PARAMETER(struct efx_channel, n_rx_tobe_disc),
+       EFX_UINT_PARAMETER(struct efx_channel, n_rx_ip_frag_err),
+       EFX_UINT_PARAMETER(struct efx_channel, n_rx_ip_hdr_chksum_err),
+       EFX_UINT_PARAMETER(struct efx_channel, n_rx_tcp_udp_chksum_err),
+       EFX_UINT_PARAMETER(struct efx_channel, n_rx_frm_trunc),
+       EFX_UINT_PARAMETER(struct efx_channel, n_rx_overlength),
+       EFX_UINT_PARAMETER(struct efx_channel, n_skbuff_leaks),
+       EFX_INT_PARAMETER(struct efx_channel, rx_alloc_level),
+       EFX_INT_PARAMETER(struct efx_channel, rx_alloc_push_pages),
+       EFX_INT_PARAMETER(struct efx_channel, rx_alloc_pop_pages),
+       {NULL},
+};
+
+static void efx_fini_debugfs_channel(struct efx_channel *channel);
+
+/**
+ * efx_init_debugfs_channel - create debugfs directory for channel
+ * @channel:           Efx channel
+ *
+ * Create a debugfs directory containing parameter-files for @channel.
+ * Return a negative error code or 0 on success.  The directory must be
+ * cleaned up using efx_fini_debugfs_channel().
+ */
+static int efx_init_debugfs_channel(struct efx_channel *channel)
+{
+       char name[EFX_DEBUGFS_NAME_LEN];
+       int rc;
+
+       /* Create directory */
+       if (snprintf(name, sizeof(name), EFX_CHANNEL_NAME(channel))
+           >= sizeof(name))
+               goto err_len;
+       channel->debug_dir = debugfs_create_dir(name, channel->efx->debug_dir);
+       if (!channel->debug_dir)
+               goto err_mem;
+
+       /* Create files */
+       rc = efx_init_debugfs_files(channel->debug_dir,
+                                   efx_debugfs_channel_parameters,
+                                   (void *)channel);
+       if (rc)
+               goto err;
+
+       return 0;
+
+ err_len:
+       rc = -ENAMETOOLONG;
+       goto err;
+ err_mem:
+       rc = -ENOMEM;
+ err:
+       efx_fini_debugfs_channel(channel);
+       return rc;
+}
+
+/**
+ * efx_fini_debugfs_channel - remove debugfs directory for channel
+ * @channel:           Efx channel
+ *
+ * Remove directory created for @channel by efx_init_debugfs_channel().
+ */
+static void efx_fini_debugfs_channel(struct efx_channel *channel)
+{
+       efx_fini_debugfs_dir(channel->debug_dir,
+                            efx_debugfs_channel_parameters, NULL);
+       channel->debug_dir = NULL;
+}
+
+/* Per-NIC parameters */
+static struct efx_debugfs_parameter efx_debugfs_nic_parameters[] = {
+       EFX_INT_PARAMETER(struct efx_nic, legacy_irq),
+       EFX_INT_PARAMETER(struct efx_nic, rss_queues),
+       EFX_UINT_PARAMETER(struct efx_nic, rx_buffer_len),
+       EFX_INT_MODE_PARAMETER(struct efx_nic, interrupt_mode),
+       {.name = "hardware_desc",
+        .offset = 0,
+        .reader = falcon_debugfs_read_hardware_desc},
+       {NULL},
+};
+
+/* Per-NIC error counts */
+static struct efx_debugfs_parameter efx_debugfs_nic_error_parameters[] = {
+       EFX_ATOMIC_PARAMETER(struct efx_nic_errors, missing_event),
+       EFX_ATOMIC_PARAMETER(struct efx_nic_errors, rx_reset),
+       EFX_ATOMIC_PARAMETER(struct efx_nic_errors, rx_desc_fetch),
+       EFX_ATOMIC_PARAMETER(struct efx_nic_errors, tx_desc_fetch),
+       EFX_ATOMIC_PARAMETER(struct efx_nic_errors, spurious_tx),
+       {NULL},
+};
+
+/**
+ * efx_init_debugfs_channels - create debugfs directories for NIC channels
+ * @efx:               Efx NIC
+ *
+ * Create subdirectories of @efx's debugfs directory for all the
+ * channels, RX queues and TX queues used by this driver.  Return a
+ * negative error code or 0 on success.  The subdirectories must be
+ * cleaned up using efx_fini_debugfs_channels().
+ */
+int efx_init_debugfs_channels(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+       struct efx_rx_queue *rx_queue;
+       struct efx_tx_queue *tx_queue;
+       int rc;
+
+       efx_for_each_channel(channel, efx) {
+               rc = efx_init_debugfs_channel(channel);
+               if (rc)
+                       goto err;
+       }
+
+       efx_for_each_rx_queue(rx_queue, efx) {
+               rc = efx_init_debugfs_rx_queue(rx_queue);
+               if (rc)
+                       goto err;
+       }
+
+       efx_for_each_tx_queue(tx_queue, efx) {
+               rc = efx_init_debugfs_tx_queue(tx_queue);
+               if (rc)
+                       goto err;
+       }
+
+       return 0;
+
+ err:
+       efx_fini_debugfs_channels(efx);
+       return rc;
+}
+
+/**
+ * efx_fini_debugfs_channels - remove debugfs directories for NIC queues
+ * @efx:               Efx NIC
+ *
+ * Remove subdirectories of @efx's debugfs directory created by
+ * efx_init_debugfs_channels().
+ */
+void efx_fini_debugfs_channels(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+       struct efx_rx_queue *rx_queue;
+       struct efx_tx_queue *tx_queue;
+
+       efx_for_each_tx_queue(tx_queue, efx)
+               efx_fini_debugfs_tx_queue(tx_queue);
+
+       efx_for_each_rx_queue(rx_queue, efx)
+               efx_fini_debugfs_rx_queue(rx_queue);
+
+       efx_for_each_channel(channel, efx)
+               efx_fini_debugfs_channel(channel);
+}
+
+/**
+ * efx_init_debugfs_nic - create debugfs directory for NIC
+ * @efx:               Efx NIC
+ *
+ * Create debugfs directory containing parameter-files for @efx,
+ * and a subdirectory "errors" containing per-NIC error counts.
+ * Return a negative error code or 0 on success.  The directories
+ * must be cleaned up using efx_fini_debugfs_nic().
+ */
+int efx_init_debugfs_nic(struct efx_nic *efx)
+{
+       int rc;
+
+       /* Create directory */
+       efx->debug_dir = debugfs_create_dir(pci_name(efx->pci_dev),
+                                           efx_debug_cards);
+       if (!efx->debug_dir)
+               goto err_mem;
+
+       /* Create errors directory */
+       efx->errors.debug_dir = debugfs_create_dir("errors", efx->debug_dir);
+       if (!efx->errors.debug_dir)
+               goto err_mem;
+
+       /* Create files */
+       rc = efx_init_debugfs_files(efx->debug_dir,
+                                   efx_debugfs_nic_parameters, (void *)efx);
+       if (rc)
+               goto err;
+       rc = efx_init_debugfs_files(efx->errors.debug_dir,
+                                   efx_debugfs_nic_error_parameters,
+                                   (void *)&efx->errors);
+       if (rc)
+               goto err;
+
+       return 0;
+
+ err_mem:
+       rc = -ENOMEM;
+ err:
+       efx_fini_debugfs_nic(efx);
+       return rc;
+}
+
+/**
+ * efx_fini_debugfs_nic - remove debugfs directories for NIC
+ * @efx:               Efx NIC
+ *
+ * Remove debugfs directories created for @efx by efx_init_debugfs_nic().
+ */
+void efx_fini_debugfs_nic(struct efx_nic *efx)
+{
+       efx_fini_debugfs_dir(efx->errors.debug_dir,
+                            efx_debugfs_nic_error_parameters, NULL);
+       efx->errors.debug_dir = NULL;
+       efx_fini_debugfs_dir(efx->debug_dir, efx_debugfs_nic_parameters, NULL);
+       efx->debug_dir = NULL;
+}
+
+/**
+ * efx_init_debugfs - create debugfs directories for sfc driver
+ *
+ * Create debugfs directories "sfc" and "sfc/cards".  This must be
+ * called before any of the other functions that create debugfs
+ * directories.  Return a negative error code or 0 on success.  The
+ * directories must be cleaned up using efx_fini_debugfs().
+ */
+int efx_init_debugfs(void)
+{
+       /* Create top-level directory */
+#if defined(EFX_USE_DEBUGFS)
+       efx_debug_root = debugfs_create_dir("sfc", NULL);
+#else
+       efx_debug_root = proc_mkdir("sfc", proc_root_driver);
+#endif
+       if (!efx_debug_root)
+               goto err;
+
+       /* Create "cards" directory */
+       efx_debug_cards = debugfs_create_dir("cards", efx_debug_root);
+       if (!efx_debug_cards)
+               goto err;
+
+#if defined(EFX_USE_DEBUGFS)
+       /* Create compatibility sym-link */
+       if (!proc_symlink("sfc", proc_root_driver, "/sys/kernel/debug/sfc"))
+               goto err;
+#endif
+       return 0;
+
+ err:
+       efx_fini_debugfs();
+       return -ENOMEM;
+}
+
+/**
+ * efx_fini_debugfs - remove debugfs directories for sfc driver
+ *
+ * Remove directories created by efx_init_debugfs().
+ */
+void efx_fini_debugfs(void)
+{
+#if defined(EFX_USE_DEBUGFS)
+       remove_proc_entry("sfc", proc_root_driver);
+#endif
+       debugfs_remove(efx_debug_cards);
+       efx_debug_cards = NULL;
+       debugfs_remove(efx_debug_root);
+       efx_debug_root = NULL;
+}
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/debugfs.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/debugfs.h Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,172 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2006-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_DEBUGFS_H
+#define EFX_DEBUGFS_H
+
+#ifdef CONFIG_SFC_DEBUGFS
+
+struct seq_file;
+
+struct efx_debugfs_parameter {
+       const char *name;
+       size_t offset;
+       int (*reader)(struct seq_file *, void *);
+};
+
+extern void efx_fini_debugfs_child(struct dentry *dir, const char *name);
+extern int efx_init_debugfs_netdev(struct net_device *net_dev);
+extern void efx_fini_debugfs_netdev(struct net_device *net_dev);
+extern int efx_init_debugfs_port(struct efx_nic *efx);
+extern void efx_fini_debugfs_port(struct efx_nic *efx);
+extern int efx_init_debugfs_nic(struct efx_nic *efx);
+extern void efx_fini_debugfs_nic(struct efx_nic *efx);
+extern int efx_init_debugfs_channels(struct efx_nic *efx);
+extern void efx_fini_debugfs_channels(struct efx_nic *efx);
+extern int efx_init_debugfs(void);
+extern void efx_fini_debugfs(void);
+extern int efx_extend_debugfs_port(struct efx_nic *efx,
+                                  void *context,
+                                  struct efx_debugfs_parameter *params);
+extern void efx_trim_debugfs_port(struct efx_nic *efx,
+                                 struct efx_debugfs_parameter *params);
+
+/* Helpers for handling debugfs entry reads */
+extern int efx_debugfs_read_uint(struct seq_file *, void *);
+extern int efx_debugfs_read_string(struct seq_file *, void *);
+extern int efx_debugfs_read_int(struct seq_file *, void *);
+extern int efx_debugfs_read_atomic(struct seq_file *, void *);
+extern int efx_debugfs_read_dword(struct seq_file *, void *);
+
+/* Handy macros for filling out parameters */
+
+/* Initialiser for a struct efx_debugfs_parameter with type-checking */
+#define EFX_PARAMETER(container_type, parameter, field_type,           \
+                       reader_function) {                              \
+       .name = #parameter,                                             \
+       .offset = ((((field_type *) 0) ==                               \
+                   &((container_type *) 0)->parameter) ?               \
+                  offsetof(container_type, parameter) :                \
+                  offsetof(container_type, parameter)),                \
+       .reader = reader_function,                                      \
+}
+
+/* Likewise, but the file name is not taken from the field name */
+#define EFX_NAMED_PARAMETER(_name, container_type, parameter, field_type, \
+                               reader_function) {                      \
+       .name = #_name,                                                 \
+       .offset = ((((field_type *) 0) ==                               \
+                   &((container_type *) 0)->parameter) ?               \
+                  offsetof(container_type, parameter) :                \
+                  offsetof(container_type, parameter)),                \
+       .reader = reader_function,                                      \
+}
+
+/* Likewise, but with one file for each of 4 lanes */
+#define EFX_PER_LANE_PARAMETER(prefix, suffix, container_type, parameter, \
+                               field_type, reader_function) {          \
+       .name = prefix "0" suffix,                                      \
+       .offset = ((((field_type *) 0) ==                               \
+                     ((container_type *) 0)->parameter) ?              \
+                   offsetof(container_type, parameter[0]) :            \
+                   offsetof(container_type, parameter[0])),            \
+       .reader = reader_function,                                      \
+},  {                                                                  \
+       .name = prefix "1" suffix,                                      \
+       .offset = offsetof(container_type, parameter[1]),               \
+       .reader = reader_function,                                      \
+}, {                                                                   \
+       .name = prefix "2" suffix,                                      \
+       .offset = offsetof(container_type, parameter[2]),               \
+       .reader = reader_function,                                      \
+}, {                                                                   \
+       .name = prefix "3" suffix,                                      \
+       .offset = offsetof(container_type, parameter[3]),               \
+       .reader = reader_function,                                      \
+}
+
+/* A string parameter (string embedded in the structure) */
+#define EFX_STRING_PARAMETER(container_type, parameter) {      \
+       .name = #parameter,                                     \
+       .offset = ((((char *) 0) ==                             \
+                   ((container_type *) 0)->parameter) ?        \
+                  offsetof(container_type, parameter) :        \
+                  offsetof(container_type, parameter)),        \
+       .reader = efx_debugfs_read_string,                      \
+}
+
+/* An unsigned integer parameter */
+#define EFX_UINT_PARAMETER(container_type, parameter)          \
+       EFX_PARAMETER(container_type, parameter,                \
+                     unsigned int, efx_debugfs_read_uint)
+
+/* A dword parameter */
+#define EFX_DWORD_PARAMETER(container_type, parameter)         \
+       EFX_PARAMETER(container_type, parameter,                \
+                     efx_dword_t, efx_debugfs_read_dword)
+
+/* An atomic_t parameter */
+#define EFX_ATOMIC_PARAMETER(container_type, parameter)                \
+       EFX_PARAMETER(container_type, parameter,                \
+                     atomic_t, efx_debugfs_read_atomic)
+
+/* An integer parameter */
+#define EFX_INT_PARAMETER(container_type, parameter)           \
+       EFX_PARAMETER(container_type, parameter,                \
+                     int, efx_debugfs_read_int)
+
+#else /* !CONFIG_SFC_DEBUGFS */
+
+static inline int efx_init_debugfs_netdev(struct net_device *net_dev)
+{
+       return 0;
+}
+static inline void efx_fini_debugfs_netdev(struct net_device *net_dev) {}
+static inline int efx_init_debugfs_port(struct efx_nic *efx)
+{
+       return 0;
+}
+static inline void efx_fini_debugfs_port(struct efx_nic *efx) {}
+static inline int efx_init_debugfs_nic(struct efx_nic *efx)
+{
+       return 0;
+}
+static inline void efx_fini_debugfs_nic(struct efx_nic *efx) {}
+static inline int efx_init_debugfs_channels(struct efx_nic *efx)
+{
+       return 0;
+}
+static inline void efx_fini_debugfs_channels(struct efx_nic *efx) {}
+static inline int efx_init_debugfs(void)
+{
+       return 0;
+}
+static inline void efx_fini_debugfs(void) {}
+
+#endif /* CONFIG_SFC_DEBUGFS */
+
+#endif /* EFX_DEBUGFS_H */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/driverlink.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/driverlink.c      Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,544 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005:      Fen Systems Ltd.
+ * Copyright 2005-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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/module.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "driverlink.h"
+
+/* Driverlink semaphore
+ * This semaphore must be held for any operation that modifies any of
+ * the driverlink lists.
+ */
+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 */
+struct efx_dl_handle {
+       /* The efx_dl_device consumers see */
+       struct efx_dl_device efx_dev;
+       /* The efx_nic providers provide */
+       struct efx_nic *efx;
+       /* Per-device list */
+       struct list_head port_node;
+       /* Per-driver list */
+       struct list_head driver_node;
+};
+
+/* Get the handle for an efx_dl_device */
+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
+ * You must hold the efx_driverlink_lock before calling this
+ * function.
+ */
+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);
+
+       /* Call driver's remove() routine */
+       if (efx_dev->driver->remove)
+               efx_dev->driver->remove(efx_dev);
+
+       /* Remove handle from per-driver and per-NIC lists */
+       list_del(&efx_handle->driver_node);
+       list_del(&efx_handle->port_node);
+
+       /* Free efx_handle structure */
+       kfree(efx_handle);
+}
+
+/* Try to add an Efx device
+ * Attempt to probe the given device with the driver, creating a
+ * new efx_dl_device. If the probe routine fails, because the driver
+ * doesn't support this port, then the 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;
+
+       /* Allocate and initialise new efx_dl_device structure */
+       efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL);
+       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);
+
+       /* Attempt driver probe */
+       rc = driver->probe(efx_dev, efx->net_dev,
+                          efx->dl_info, efx->silicon_rev);
+       if (rc)
+               goto fail;
+
+       /* Add device to per-driver and per-NIC lists */
+       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_dev);
+}
+
+/**
+ * efx_dl_unregister_driver - unregister an Efx device driver
+ * @driver:            Efx driverlink driver
+ *
+ * Unregisters an Efx driver.  The driver's remove() method will be
+ * called for all Efx devices currently claimed by the driver.
+ */
+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);
+
+       /* Acquire lock.  We can't return failure, so have to use
+        * down() instead of down_interruptible()
+        */
+       mutex_lock(&efx_driverlink_lock);
+
+       /* Remove all devices claimed by the driver */
+       list_for_each_entry_safe(efx_handle, efx_handle_n,
+                                &driver->device_list, driver_node)
+               efx_dl_del_device(&efx_handle->efx_dev);
+
+       /* Remove driver from driver list */
+       list_del(&driver->node);
+
+       /* Release lock */
+       mutex_unlock(&efx_driverlink_lock);
+}
+EXPORT_SYMBOL(efx_dl_unregister_driver);
+
+/**
+ * efx_dl_register_driver - register an Efx device driver
+ * @driver:            Efx driverlink driver
+ *
+ * Registers a new Efx driver.  The driver's probe() method will be
+ * called for all Efx NICs currently registered.
+ *
+ * Return a negative error code or 0 on success.
+ */
+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);
+
+       /* Initialise driver list structures */
+       INIT_LIST_HEAD(&driver->node);
+       INIT_LIST_HEAD(&driver->device_list);
+
+       /* Acquire lock */
+       rc = mutex_lock_interruptible(&efx_driverlink_lock);
+       if (rc)
+               return rc;
+
+       /* Add driver to driver list */
+       list_add_tail(&driver->node, &efx_driver_list);
+
+       /* Feed all existing devices to driver */
+       list_for_each_entry(efx, &efx_port_list, dl_node)
+               efx_dl_try_add_device(efx, driver);
+
+       /* Release locks */
+       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;
+
+       if (!efx)
+               return;
+
+       /* Acquire lock.  We can't return failure, so have to use
+        * down() instead of down_interruptible()
+        */
+       mutex_lock(&efx_driverlink_lock);
+
+       /* Remove all devices related to this NIC */
+       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);
+
+       /* Remove port from port list */
+       list_del(&efx->dl_node);
+
+       /* Release lock */
+       mutex_unlock(&efx_driverlink_lock);
+}
+
+int efx_dl_register_nic(struct efx_nic *efx)
+{
+       struct efx_dl_driver *driver;
+       int rc;
+
+       /* Acquire lock */
+       rc = mutex_lock_interruptible(&efx_driverlink_lock);
+       if (rc)
+               return rc;
+
+       /* Add port to port list */
+       list_add_tail(&efx->dl_node, &efx_port_list);
+
+       /* Feed port to all existing drivers */
+       list_for_each_entry(driver, &efx_driver_list, node)
+               efx_dl_try_add_device(efx, driver);
+
+       /* Release lock */
+       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.
+ */
+#if defined(EFX_USE_FASTCALL)
+static enum efx_veto fastcall
+#else
+static enum efx_veto
+#endif
+efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev, struct sk_buff 
*skb)
+{
+       /* Never veto the packet */
+       return EFX_ALLOW_PACKET;
+}
+
+#if defined(EFX_USE_FASTCALL)
+static enum efx_veto fastcall
+#else
+static enum efx_veto
+#endif
+efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev,
+                            const char *pkt_buf, int len)
+{
+       /* Never veto the packet */
+       return EFX_ALLOW_PACKET;
+}
+
+static void
+efx_dummy_link_change_callback(struct efx_dl_device *efx_dev, int link_up)
+{
+}
+
+static int
+efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev, int new_mtu)
+{
+       /* Always allow */
+       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,
+       .link_change    = efx_dummy_link_change_callback,
+       .request_mtu    = efx_dummy_request_mtu_callback,
+       .mtu_changed    = efx_dummy_mtu_changed_callback,
+       .event          = efx_dummy_event_callback,
+};
+
+#define EFX_DL_UNREGISTER_CALLBACK(_port, _dev, _member)               \
+       do {                                                            \
+               BUG_ON((_port)->dl_cb_dev._member != (_dev));           \
+               (_port)->dl_cb._member =                                \
+                       efx_default_callbacks._member;                  \
+               (_port)->dl_cb_dev._member = NULL;                      \
+       } while (0)
+
+
+#define EFX_DL_REGISTER_CALLBACK(_port, _dev, _from, _member)          \
+       if ((_from)->_member) {                                         \
+               BUG_ON((_port)->dl_cb_dev._member != NULL);             \
+               (_port)->dl_cb._member = (_from)->_member;              \
+               (_port)->dl_cb_dev._member = _dev;                      \
+       }
+
+/**
+ * efx_dl_unregister_callbacks - unregister callbacks for an Efx NIC
+ * @efx_dev:           Efx driverlink device
+ * @callbacks:         Callback list
+ *
+ * This removes a set of callbacks registered with
+ * efx_dl_register_callbacks().  It should be called as part of the
+ * client's remove() method.
+ *
+ * The net driver will ensure that all callback functions have
+ * returned to the net driver before efx_dl_unregister_callbacks()
+ * returns.  Note that the device itself may still be running when the
+ * client's remove() method is called.  The client must therefore
+ * unhook its callbacks using efx_dl_unregister_callbacks() and only
+ * then ensure that any delayed tasks triggered by callback methods
+ * (e.g. scheduled tasklets) have completed.
+ */
+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;
+
+       /* Suspend net driver operations */
+       efx_suspend(efx);
+
+       EFX_INFO(efx, "removing callback hooks into %s driver\n",
+                efx_dev->driver->name);
+
+       if (callbacks->tx_packet)
+               EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, tx_packet);
+
+       if (callbacks->rx_packet)
+               EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, rx_packet);
+
+       if (callbacks->link_change)
+               EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, link_change);
+
+       if (callbacks->request_mtu)
+               EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, request_mtu);
+
+       if (callbacks->mtu_changed)
+               EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, mtu_changed);
+
+       if (callbacks->event)
+               EFX_DL_UNREGISTER_CALLBACK(efx, efx_dev, event);
+
+       /* Resume net driver operations */
+       efx_resume(efx);
+}
+EXPORT_SYMBOL(efx_dl_unregister_callbacks);
+
+/**
+ * efx_dl_register_callbacks - register callbacks for an Efx NIC
+ * @efx_dev:           Efx driverlink device
+ * @callbacks:         Callback list
+ *
+ * This registers a set of callback functions with the net driver.
+ * These functions will be called at various key points to allow
+ * external code to monitor and/or modify the behaviour of the network
+ * driver.  Any of the callback function pointers may be %NULL if a
+ * callback is not required.  The intended user of this mechanism is
+ * the SFC char driver.
+ *
+ * This client should call efx_dl_register_callbacks() during its
+ * probe() method.  The client must ensure that it also calls
+ * efx_dl_unregister_callbacks() as part of its remove() method.
+ *
+ * Only one function may be registered for each callback per NIC.
+ * If a requested callback is already registered for this NIC, this
+ * function will return -%EBUSY.
+ *
+ * The device may already be running, so the client must be prepared
+ * for callbacks to be triggered immediately after calling
+ * efx_dl_register_callbacks().
+ *
+ * Return a negative error code or 0 on success.
+ */
+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;
+
+       /* Suspend net driver operations */
+       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->link_change && efx->dl_cb_dev.link_change) ||
+           (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 callbacks.  For maximum speed, we never check to
+        * see whether these are NULL before calling; therefore we
+        * must ensure that they are never NULL.  If the set we're
+        * being asked to hook in is sparse, we leave the default
+        * values in place for the empty hooks.
+        */
+       EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, tx_packet);
+       EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, rx_packet);
+       EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, link_change);
+       EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, request_mtu);
+       EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, mtu_changed);
+       EFX_DL_REGISTER_CALLBACK(efx, efx_dev, callbacks, event);
+
+ out:
+       /* Resume net driver operations */
+       efx_resume(efx);
+
+       return rc;
+}
+EXPORT_SYMBOL(efx_dl_register_callbacks);
+
+/**
+ * efx_dl_schedule_reset - schedule an Efx NIC reset
+ * @efx_dev:           Efx driverlink device
+ *
+ * This schedules a hardware reset for a short time in the future.  It
+ * can be called from any context, and so can be used when
+ * efx_dl_reset() cannot be called.
+ */
+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);
+
+/*
+ * Lock the driverlink layer before a reset
+ * To avoid deadlock, efx_driverlink_lock needs to be acquired before
+ * efx->suspend_lock.
+ */
+void efx_dl_reset_lock(void)
+{
+       /* Acquire lock */
+       mutex_lock(&efx_driverlink_lock);
+}
+
+/*
+ * Unlock the driverlink layer after a reset
+ * This call must be matched against efx_dl_reset_lock.
+ */
+void efx_dl_reset_unlock(void)
+{
+       /* Acquire lock */
+       mutex_unlock(&efx_driverlink_lock);
+}
+
+/*
+ * Suspend ready for reset
+ * This calls the reset_suspend method of all drivers registered to
+ * the specified NIC.  It must only be called between
+ * efx_dl_reset_lock and efx_dl_reset_unlock.
+ */
+void efx_dl_reset_suspend(struct efx_nic *efx)
+{
+       struct efx_dl_handle *efx_handle;
+       struct efx_dl_device *efx_dev;
+
+       BUG_ON(!mutex_is_locked(&efx_driverlink_lock));
+
+       /* Call suspend method of each driver in turn */
+       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
+ * This calls the reset_resume method of all drivers registered to the
+ * specified NIC.  It must only be called between efx_dl_reset_lock
+ * and efx_dl_reset_unlock.
+ */
+void efx_dl_reset_resume(struct efx_nic *efx, int ok)
+{
+       struct efx_dl_handle *efx_handle;
+       struct efx_dl_device *efx_dev;
+
+       BUG_ON(!mutex_is_locked(&efx_driverlink_lock));
+
+       /* Call resume method of each driver in turn */
+       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);
+       }
+}
+
+/**
+ * efx_dl_get_nic - obtain the Efx NIC for the given driverlink device
+ * @efx_dev:           Efx driverlink device
+ *
+ * Get a pointer to the &struct efx_nic corresponding to
+ * @efx_dev.  This can be used by driverlink clients built along with
+ * the sfc driver, which may have intimate knowledge of its internals.
+ */
+struct efx_nic *efx_dl_get_nic(struct efx_dl_device *efx_dev)
+{
+       return efx_dl_handle(efx_dev)->efx;
+}
+EXPORT_SYMBOL(efx_dl_get_nic);
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/driverlink.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/driverlink.h      Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,93 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005:      Fen Systems Ltd.
+ * Copyright 2006:      Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_DRIVERLINK_H
+#define EFX_DRIVERLINK_H
+
+/* Forward declarations */
+struct efx_dl_device;
+struct efx_nic;
+
+/*
+ * Efx driverlink
+ *
+ * This header file defines the portions of the Efx driverlink
+ * interface that are used only within the sfc module.  It also
+ * declares efx_dl_get_nic(), which may be used by sfc_mtd
+ * and any other module built along with sfc.
+ */
+
+
+/* Efx callback devices
+ *
+ * A list of the devices that own each callback. The partner to
+ * struct efx_dl_callbacks
+ */
+struct efx_dl_cb_devices {
+       /* Device owning the tx_packet callback */
+       struct efx_dl_device *tx_packet;
+       /* Device owning the rx_packet callback */
+       struct efx_dl_device *rx_packet;
+       /* Device owning the link_change callback. */
+       struct efx_dl_device *link_change;
+       /* Device owning the request_mtu callback. */
+       struct efx_dl_device *request_mtu;
+       /* Device owning the mtu_changed callback. */
+       struct efx_dl_device *mtu_changed;
+       /* Device owning the event callback. */
+       struct efx_dl_device *event;
+};
+
+/* No-op callbacks used for initialisation */
+extern struct efx_dl_callbacks efx_default_callbacks;
+
+/* Macro used to invoke callbacks */
+#define EFX_DL_CALLBACK(_port, _name, ...)                             \
+       (_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__)
+
+/* Register an Efx NIC */
+extern int efx_dl_register_nic(struct efx_nic *efx);
+
+/* Unregister an Efx NIC */
+extern void efx_dl_unregister_nic(struct efx_nic *efx);
+
+/* Lock the driverlink layer prior to a reset */
+extern void efx_dl_reset_lock(void);
+
+/* Unlock the driverlink layer following a reset */
+extern void efx_dl_reset_unlock(void);
+
+/* Suspend all drivers prior to a hardware reset */
+extern void efx_dl_reset_suspend(struct efx_nic *efx);
+
+/* Resume all drivers after a hardware reset */
+extern void efx_dl_reset_resume(struct efx_nic *efx, int ok);
+
+/* Obtain the Efx NIC for the given driverlink device. */
+extern struct efx_nic *efx_dl_get_nic(struct efx_dl_device *efx_dev);
+
+#endif /* EFX_DRIVERLINK_H */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/driverlink_api.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/driverlink_api.h  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,612 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2005-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_DRIVERLINK_API_H
+#define EFX_DRIVERLINK_API_H
+
+#include <linux/list.h> /* for struct list_head */
+#if !defined(EFX_USE_FASTCALL)
+       #include <linux/version.h>
+       #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+               #define EFX_USE_FASTCALL yes
+               #include <linux/linkage.h>
+       #endif
+#endif
+
+/**
+ * DOC: Efx driverlink API
+ *
+ * This file must be included by any driver that wishes to attach to
+ * devices claimed by the Solarflare NIC driver (sfc). It allows separate
+ * kernel modules to expose other functionality offered by the NIC, with
+ * the sfc driver remaining in overall control.
+ *
+ * Overview:
+ *
+ * Driverlink clients define a &struct efx_dl_driver, and register
+ * this structure with the driverlink layer using
+ * efx_dl_register_driver(), which is exported by the sfc driver.
+ *
+ * The probe() routine of each driverlink client driver is called by
+ * the driverlink layer for each physical port in the system, after
+ * the sfc driver has performed start-of-day hardware initialisation
+ * and self-test. If ports are added or removed via pci hotplug then
+ * the &struct efx_dl_driver probe() or remove() routines are called
+ * as appropriate.
+ *
+ * If the port doesn't provide the necessary hardware resources for a
+ * client, then that client can return failure from its probe()
+ * routine. Information provided to the client driver at probe time
+ * includes
+ *
+ * Each probe() routine is given a unique &struct efx_dl_device per
+ * port, which means it can safely use the @priv member to store any
+ * useful state it needs. The probe routine also has the opportunity
+ * to provide a &struct efx_dl_callbacks via
+ * efx_dl_register_callbacks(), which allows the client to intercept
+ * the sfc driver's operations at strategic points.
+ *
+ * Occasionally, the underlying Efx device may need to be reset to
+ * recover from an error condition.  The client's reset_suspend() and
+ * reset_resume() methods [if provided] will be called to enable the
+ * client to suspend operations and preserve any state before the
+ * reset.  The client can itself request a reset using efx_dl_reset()
+ * or efx_dl_schedule_reset(), should it detect an error condition
+ * necessitating a reset.
+ *
+ * Example:
+ *
+ * The MTD driver (mtd.c) uses the driverlink layer.
+ */
+
+/* Forward declarations */
+struct pci_dev;
+struct net_device;
+struct sk_buff;
+struct efx_dl_device;
+struct efx_dl_device_info;
+
+/*
+ * This is used to guard against the registration of driverlink
+ * clients using an incorrect version of the API.
+ */
+#define EFX_DRIVERLINK_API_VERSION 1
+
+
+/**
+ * struct efx_dl_driver - An Efx driverlink device driver
+ *
+ * This is the analogue of a struct pci_driver for a normal PCI
+ * driver.  Driverlink clients should register themselves using
+ * efx_dl_register_driver() at module initialisation, and deregister
+ * themselves using efx_dl_unregister_driver() at module exit.
+ *
+ * All calls to members of efx_dl_driver are serialised by a single
+ * semaphore, so you are allowed to sleep in these functions. Take care
+ * to not call driverlink methods from within these callbacks, otherwise
+ * a deadlock is possible.
+ *
+ * @name: Name of the driver
+ * @probe: Called when device added
+ * @remove: Called when device removed
+ * @reset_suspend: Called before device is reset
+ * @reset_resume: Called after device is reset
+ */
+struct efx_dl_driver {
+       const char *name;
+
+       /*
+        * probe - Handle device addition.
+        * @efx_dev:            Efx driverlink device
+        * @net_dev:            The net_dev relevant to this port
+        * @dev_info:           A linked list of device information.
+        * @silicon_rev:        Silicon revision name.
+        *
+        * This will be called after driverlink client registration for
+        * every port on the system, and for every port that appears
+        * thereafter via hotplug.
+        *
+        * The client may use either @efx_dev->pci_dev, the dev_info linked
+        * list of available driver information, or the silicon revision
+        * name to determine if they can support this port. If they can,
+        * they should return 0 to indicate the probe was successful. Any
+        * other return code indicates that the probe failed, and the
+        * @efx_dl_dev will be invalidated.
+        *
+        * The client should perform whatever initialisation it
+        * requires, and store a pointer to its private data in
+        * @efx_dl_dev->priv (which is not shared between clients).
+        * It may also wish to hook in a callbacks table using
+        * efx_dl_register_callbacks().
+        *
+        * Return a negative error code or 0 on success.
+        */
+       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);
+
+       /*
+        * remove - Handle device removal.
+        * @efx_dev:            Efx driverlink device
+        *
+        * This will be called at driver exit (or hotplug removal) for
+        * each registered driverlink client.
+        *
+        * The client must ensure that it has finished all operations
+        * using this device before returning from this method.  If it
+        * has hooked in a callbacks table using
+        * efx_dl_register_callbacks(), it must unhook it using
+        * efx_dl_unregister_callbacks(), and then ensure that all
+        * callback-triggered operations (e.g. scheduled tasklets)
+        * have completed before returning.  (It does not need to
+        * explicitly wait for callback methods to finish executing,
+        * since efx_dl_unregister_callbacks() will sleep until all
+        * callbacks have returned anyway.)
+        *
+        * Note that the device itself may not have been removed; it
+        * may be simply that the client is being unloaded
+        * via efx_dl_unregister_driver(). In this case other clients
+        * (and the sfc driver itself) will still be using the device,
+        * so the client cannot assume that the device itself is quiescent.
+        * In particular, callbacks may continue to be triggered at any
+        * point until efx_dl_unregister_callbacks() is called.
+        */
+       void (*remove) (struct efx_dl_device *efx_dev);
+
+       /*
+        * reset_suspend - Suspend ready for reset.
+        * @efx_dev:            Efx driverlink device
+        *
+        * This method will be called immediately before a hardware
+        * reset (which may or may not have been initiated by the
+        * driverlink client).  This client must save any state that it
+        * will need to restore after the reset, and suspend all
+        * operations that might access the hardware.  It must not
+        * return until the client can guarantee to have stopped
+        * touching the hardware.
+        *
+        * It is guaranteed that callbacks will be inactive by the
+        * time this method is called; the driverlink layer will
+        * already have prevented new callbacks being made and waited
+        * for all callbacks functions to return before calling
+        * reset_suspend().  However, any delayed work scheduled by
+        * the callback functions (e.g. tasklets) may not yet have
+        * completed.
+        *
+        * This method is allowed to sleep, so waiting on tasklets,
+        * work queues etc. is permitted.  There will always be a
+        * corresponding call to the reset_resume() method, so it is
+        * safe to e.g. down a semaphore within reset_suspend() and up
+        * it within reset_resume().  (However, you obviously cannot
+        * do the same with a spinlock).
+        *
+        * Note that the reset operation may be being carried out in
+        * the context of scheduled work, so you cannot use
+        * flush_scheduled_work() to ensure that any work you may have
+        * scheduled has completed.
+        *
+        * During hardware reset, there is a chance of receiving
+        * spurious interrupts, so the client's ISR (if any) should be
+        * unhooked or otherwise disabled.
+        */
+       void (*reset_suspend) (struct efx_dl_device *efx_dev);
+
+       /*
+        * reset_resume - Restore after a reset.
+        * @efx_dev:            Efx driverlink device
+        * @ok:                 Reset success indicator
+        *
+        * This method will be called after a hardware reset.  There
+        * will always have been a corresponding call to the
+        * reset_suspend() method beforehand.
+        *
+        * If @ok is non-zero, the client should restore the state
+        * that it saved during the call to reset_suspend() and resume
+        * normal operations.
+        *
+        * If @ok is zero, the reset operation has failed and the
+        * hardware is currently in an unusable state.  In this case,
+        * the client should release any locks taken out by
+        * reset_suspend(), but should not take any other action; in
+        * particular, it must not access the hardware, nor resume
+        * normal operations.  The hardware is effectively dead at
+        * this point, and our sole aim is to avoid deadlocking or
+        * crashing the host.
+        *
+        * The driverlink layer will still be locked when
+        * reset_resume() is called, so the client may not call
+        * driverlink functions.  In particular, if the reset failed,
+        * the client must not call efx_dl_unregister_callbacks() at
+        * this point; it should wait until remove() is called.
+        */
+       void (*reset_resume) (struct efx_dl_device *efx_dev, int ok);
+
+/* private: */
+       struct list_head node;
+       struct list_head device_list;
+};
+
+/**
+ * DOC: Efx driverlink device information
+ *
+ * Each &struct efx_dl_device makes certain hardware resources visible
+ * to driverlink clients, and they describe which resources are
+ * available by passing a linked list of &struct efx_dl_device_info
+ * into the probe() routine.
+ *
+ * The driverlink client's probe function can iterate through the linked list,
+ * and provided that it understands the resources that are exported, it can
+ * choose to make use of them through an external interface.
+ */
+
+/**
+ * enum efx_dl_device_info_type - Device information identifier.
+ *
+ * Each distinct hardware resource API will have a member in this
+ * enumeration.
+ *
+ * @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
+ *
+ * This structure is embedded in other structures provided by the
+ * driverlink device provider, and implements a linked list of
+ * resources pertinent to a driverlink client.
+ *
+ * Example: &struct efx_dl_falcon_resources
+ */
+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 described Falcon based port.
+ *
+ * @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. See the discussion of @pci_dev in &struct efx_dl_device
+ *     below.
+ * @EFX_DL_FALCON_USE_MSI: Port is initialised to use MSI/MSI-X interrupts.
+ *     Falcon supports traditional legacy interrupts and MSI/MSI-X
+ *     interrupts. Since the sfc driver supports either, as a run
+ *     time configuration, driverlink drivers need to be aware of which
+ *     one to use for their interrupting resources.
+ */
+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_max: Last available buffer table entry + 1
+ * @evq_timer_min: First available event queue with timer
+ * @evq_timer_max: Last available event queue with timer + 1
+ * @evq_int_min: First available event queue with interrupt
+ * @evq_int_max: Last available event queue with interrupt + 1
+ * @rxq_min: First available RX queue
+ * @rxq_max: Last available RX queue + 1
+ * @txq_min: First available TX queue
+ * @txq_max: 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, buffer_table_max;
+       unsigned evq_timer_min, evq_timer_max;
+       unsigned evq_int_min, evq_int_max;
+       unsigned rxq_min, rxq_max;
+       unsigned txq_min, txq_max;
+       enum efx_dl_falcon_resource_flags flags;
+};
+
+/**
+ * struct efx_dl_device - An Efx driverlink device.
+ *
+ * @pci_dev: Underlying PCI device.
+ *     This is the PCI device used by the sfc driver.  It will
+ *     already have been enabled for bus-mastering DMA etc.
+ * @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
+ *
+ * These methods can be hooked in to the sfc driver via
+ * efx_dl_register_callbacks().  They allow clients to intercept and/or
+ * modify the behaviour of the sfc driver at predetermined points.
+ *
+ * For efficiency, only one client can hook each callback.
+ *
+ * Since these callbacks are called on packet transmit and reception
+ * paths, clients should avoid acquiring locks or allocating memory.
+ *
+ * @tx_packet: Called when packet is about to be transmitted
+ * @rx_packet: Called when packet is received
+ * @link_change: Called when link status has changed
+ * @request_mtu: Called to request MTU change
+ * @mtu_changed: Called when MTU has been changed
+ * @event: Called when NIC event is not handled by the sfc driver
+ */
+struct efx_dl_callbacks {
+       /*
+        * tx_packet - Packet about to be transmitted.
+        * @efx_dev:            Efx driverlink device
+        * @skb:                Socket buffer containing the packet to be sent
+        *
+        * This method is called for every packet about to be
+        * transmitted.  It allows the client to snoop on traffic sent
+        * via the kernel queues.
+        *
+        * The method may return %EFX_VETO_PACKET in order to prevent
+        * the sfc driver from transmitting the packet.  The net
+        * driver will then discard the packet.  If the client wishes
+        * to retain a reference to the packet data after returning
+        * %EFX_VETO_PACKET, it must obtain its own copy of the
+        * packet (e.g. by calling skb_get(), or by copying out the
+        * packet data to an external buffer).
+        *
+        * This method must return quickly, since it will have a
+        * direct performance impact upon the sfc driver.  It will be
+        * called with interrupts disabled (and may be called in
+        * interrupt context), so may not sleep. Since the sfc driver
+        * may have multiple TX queues, running in parallel, please avoid
+        * the need for locking if it all possible.
+        */
+#if defined(EFX_USE_FASTCALL)
+       enum efx_veto fastcall (*tx_packet) (struct efx_dl_device *efx_dev,
+                                            struct sk_buff *skb);
+#else
+       enum efx_veto (*tx_packet) (struct efx_dl_device *efx_dev,
+                                   struct sk_buff *skb);
+#endif
+
+       /*
+        * rx_packet - Packet received.
+        * @efx_dev:            Efx driverlink device
+        * @pkt_hdr:            Pointer to received packet
+        * @pkt_len:            Length of received packet
+        *
+        * This method is called for every received packet.  It allows
+        * the client to snoop on traffic received by the kernel
+        * queues.
+        *
+        * The method may return %EFX_VETO_PACKET in order to prevent
+        * the sfc driver from passing the packet to the kernel.  The net
+        * driver will then discard the packet.
+        *
+        * This method must return quickly, since it will have a
+        * direct performance impact upon the sfc driver.  It is
+        * called in tasklet context, so may not sleep.  Note that
+        * there are per-channel tasklets in the sfc driver, so
+        * rx_packet() may be called simultaneously on different CPUs
+        * and must lock appropriately.  The design of the sfc driver
+        * allows for lockless operation between receive channels, so
+        * please avoid the need for locking if at all possible.
+        */
+#if defined(EFX_USE_FASTCALL)
+       enum efx_veto fastcall (*rx_packet) (struct efx_dl_device *efx_dev,
+                                            const char *pkt_hdr, int pkt_len);
+#else
+       enum efx_veto (*rx_packet) (struct efx_dl_device *efx_dev,
+                                   const char *pkt_hdr, int pkt_len);
+#endif
+
+       /*
+        * link_change - Link status change.
+        * @efx_dev:            Efx driverlink device
+        * @link_up:            Link up indicator
+        *
+        * This method is called to inform the driverlink client
+        * whenever the PHY link status changes.  By the time this
+        * function is called, the MAC has already been reconfigured
+        * with the new autonegotiation settings from the PHY.
+        *
+        * This method is called from tasklet context and may not
+        * sleep.
+        */
+       void (*link_change) (struct efx_dl_device *efx_dev, int link_up);
+
+       /*
+        * request_mtu: Request MTU change.
+        * @efx_dev:            Efx driverlink device
+        * @new_mtu:            Requested new MTU
+        *
+        * This method is called whenever the user requests an MTU
+        * change on an interface.  The client may return an error, in
+        * which case the MTU change request will be denied.  If the
+        * client returns success, the MAC will be reconfigured with a
+        * new maxmimum frame length equal to
+        * EFX_MAX_FRAME_LEN(new_mtu).  The client will be notified
+        * via the mtu_changed() method once the MAC has been
+        * reconfigured.
+        *
+        * The current MTU for the port can be obtained via
+        * efx_dl_get_netdev(efx_dl_device)->mtu.
+        *
+        * The sfc driver guarantees that no other callback functions
+        * are in progress when this method is called.  This function
+        * is called in process context and may sleep.
+        *
+        * Return a negative error code or 0 on success.
+        */
+       int (*request_mtu) (struct efx_dl_device *efx_dev, int new_mtu);
+
+       /*
+        * mtu_changed - MTU has been changed.
+        * @efx_dev:            Efx driverlink device
+        * @mtu:                The new MTU
+        *
+        * This method is called once the MAC has been reconfigured
+        * with a new MTU.  There will have been a preceding call to
+        * request_mtu().
+        *
+        * The sfc driver guarantees that no other callback functions
+        * are in progress when this method is called.  This function
+        * is called in process context and may sleep.
+        */
+       void (*mtu_changed) (struct efx_dl_device *efx_dev, int mtu);
+
+       /*
+        * event - Event callback.
+        * @efx_dev:            Efx driverlink device
+        * @p_event:            Pointer to event
+        *
+        * This method is called for each event that is not handled by the
+        * sfc driver.
+        */
+       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)
+
+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);
+
+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:
+ *
+ * static int driver_dl_probe(... const struct efx_dl_device_info *dev_info 
...)
+ * {
+ *        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:
+ *
+ * static int driver_dl_probe(... const struct efx_dl_device_info *dev_info 
...)
+ * {
+ *        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 != NULL) {
+ *                 ....
+ *        }
+ * }
+ */
+#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 */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/efx.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/efx.c     Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,2783 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2005-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/in.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+#include "net_driver.h"
+#include "gmii.h"
+#include "driverlink.h"
+#include "selftest.h"
+#include "debugfs.h"
+#include "ethtool.h"
+#include "tx.h"
+#include "rx.h"
+#include "efx.h"
+#include "mdio_10g.h"
+#include "falcon.h"
+#include "workarounds.h"
+
+/**************************************************************************
+ *
+ * Type name strings
+ *
+ **************************************************************************
+ */
+
+/* Loopback mode names (see LOOPBACK_MODE()) */
+const unsigned int efx_loopback_mode_max = LOOPBACK_MAX;
+const char *efx_loopback_mode_names[] = {
+       [LOOPBACK_NONE]    = "NONE",
+       [LOOPBACK_MAC]     = "MAC",
+       [LOOPBACK_XGMII]   = "XGMII",
+       [LOOPBACK_XGXS]    = "XGXS",
+       [LOOPBACK_XAUI]    = "XAUI",
+       [LOOPBACK_PHY]     = "PHY",
+       [LOOPBACK_PHYXS]   = "PHY(XS)",
+       [LOOPBACK_PCS]     = "PHY(PCS)",
+       [LOOPBACK_PMAPMD]  = "PHY(PMAPMD)",
+       [LOOPBACK_NETWORK] = "NETWORK",
+};
+
+/* Interrupt mode names (see INT_MODE())) */
+const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
+const char *efx_interrupt_mode_names[] = {
+       [EFX_INT_MODE_MSIX]   = "MSI-X",
+       [EFX_INT_MODE_MSI]    = "MSI",
+       [EFX_INT_MODE_LEGACY] = "legacy",
+};
+
+/* PHY type names (see PHY_TYPE())) */
+const unsigned int efx_phy_type_max = PHY_TYPE_MAX;
+const char *efx_phy_type_names[] = {
+       [PHY_TYPE_NONE]        = "none",
+       [PHY_TYPE_CX4_RTMR]    = "Mysticom CX4",
+       [PHY_TYPE_1G_ALASKA]   = "1G Alaska",
+       [PHY_TYPE_10XPRESS]    = "SFC 10Xpress",
+       [PHY_TYPE_XFP]         = "Quake XFP",
+       [PHY_TYPE_PM8358]      = "PM8358 XAUI",
+};
+
+const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
+const char *efx_reset_type_names[] = {
+       [RESET_TYPE_INVISIBLE]    = "INVISIBLE",
+       [RESET_TYPE_ALL]          = "ALL",
+       [RESET_TYPE_WORLD]        = "WORLD",
+       [RESET_TYPE_DISABLE]      = "DISABLE",
+       [RESET_TYPE_MONITOR]      = "MONITOR",
+       [RESET_TYPE_INT_ERROR]    = "INT_ERROR",
+       [RESET_TYPE_RX_RECOVERY]  = "RX_RECOVERY",
+};
+
+const unsigned int efx_nic_state_max = STATE_MAX;
+const char *efx_nic_state_names[] = {
+       [STATE_INIT]          = "INIT",
+       [STATE_RUNNING]       = "RUNNING",
+       [STATE_FINI]          = "FINI",
+       [STATE_RESETTING]     = "RESETTING",
+       [STATE_DISABLED]      = "DISABLED",
+};
+
+#define EFX_MAX_MTU (9 * 1024)
+
+
+/**************************************************************************
+ *
+ * Configurable values
+ *
+ *************************************************************************/
+
+/*
+ * Use separate channels for TX and RX events
+ *
+ * Set this to 1 to use separate channels for TX and RX. It allows us to
+ * apply a higher level of interrupt moderation to TX events.
+ *
+ * This is forced to 0 for MSI interrupt mode as the interrupt vector
+ * is not written
+ */
+static unsigned int separate_tx_and_rx_channels = 1;
+
+/* This is the weight assigned to each of the (per-channel) virtual
+ * NAPI devices.
+ */
+static int napi_weight = 64;
+
+/* This is the time (in jiffies) between invocations of the hardware
+ * monitor, which checks for known hardware bugs and resets the
+ * hardware and driver as necessary.
+ */
+unsigned int efx_monitor_interval = 1 * HZ;
+
+/* This controls whether or not the hardware monitor will trigger a
+ * reset when it detects an error condition.
+ */
+static unsigned int monitor_reset = 1;
+
+/* This controls whether or not the driver will initialise devices
+ * with invalid MAC addresses stored in the EEPROM or flash.  If true,
+ * such devices will be initialised with a random locally-generated
+ * MAC address.  This allows for loading the efx_mtd driver to
+ * reprogram the flash, even if the flash contents (including the MAC
+ * address) have previously been erased.
+ */
+static unsigned int allow_bad_hwaddr;
+
+/* Initial interrupt moderation settings.  They can be modified after
+ * module load with ethtool.
+ *
+ * The default for RX should strike a balance between increasing the
+ * round-trip latency and reducing overhead.
+ */
+static unsigned int rx_irq_mod_usec = 60;
+
+/* Initial interrupt moderation settings.  They can be modified after
+ * module load with ethtool.
+ *
+ * This default is chosen to ensure that a 10G link does not go idle
+ * while a TX queue is stopped after it has become full.  A queue is
+ * restarted when it drops below half full.  The time this takes (assuming
+ * worst case 3 descriptors per packet and 1024 descriptors) is
+ *   512 / 3 * 1.2 = 205 usec.
+ */
+static unsigned int tx_irq_mod_usec = 150;
+
+/* Ignore online self-test failures at load
+ *
+ * If set to 1, then the driver will not fail to load
+ * if the online self-test fails. Useful only during testing
+ */
+static unsigned int allow_load_on_failure;
+
+/* Set to 1 to enable the use of Message-Signalled Interrupts (MSI).
+ * MSI will not work on some motherboards due to limitations of the
+ * chipset, so the default is off.
+ *
+ * This is the highest capability interrupt mode to use
+ * 0 => MSI-X
+ * 1 => MSI
+ * 2 => legacy
+ */
+static unsigned int interrupt_mode;
+
+/* If set to 1, then the driver will perform an offline self test
+ * when each interface first comes up. This will appear like the
+ * interface bounces up and down
+ */
+static unsigned int onload_offline_selftest = 1;
+
+/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS),
+ * i.e. the number of CPUs among which we may distribute simultaneous
+ * interrupt handling.
+ *
+ * Cards without MSI-X will only target one CPU
+ *
+ * Default (0) means to use all CPUs in the system.  This parameter
+ * can be set using "rss_cpus=xxx" when loading the module.
+ */
+static unsigned int rss_cpus;
+module_param(rss_cpus, uint, 0444);
+MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
+
+/**************************************************************************
+ *
+ * Utility functions and prototypes
+ *
+ *************************************************************************/
+static void efx_remove_channel(struct efx_channel *channel);
+static void efx_remove_port(struct efx_nic *efx);
+static void efx_fini_napi(struct efx_nic *efx);
+static void efx_fini_channels(struct efx_nic *efx);
+
+/**************************************************************************
+ *
+ * Event queue processing
+ *
+ *************************************************************************/
+
+/* Process channel's event queue
+ *
+ * This function is responsible for processing the event queue of a
+ * single channel.  The caller must guarantee that this function will
+ * never be concurrently called more than once on the same channel,
+ * though different channels may be being processed concurrently.
+ */
+static inline int efx_process_channel(struct efx_channel *channel, int 
rx_quota)
+{
+       int rxdmaqs;
+       struct efx_rx_queue *rx_queue;
+
+       if (unlikely(channel->efx->reset_pending != RESET_TYPE_NONE ||
+                    !channel->enabled))
+               return rx_quota;
+
+       rxdmaqs = falcon_process_eventq(channel, &rx_quota);
+
+       /* Deliver last RX packet. */
+       if (channel->rx_pkt) {
+               __efx_rx_packet(channel, channel->rx_pkt,
+                               channel->rx_pkt_csummed);
+               channel->rx_pkt = NULL;
+       }
+
+       efx_rx_strategy(channel);
+
+       /* Refill descriptor rings as necessary */
+       rx_queue = &channel->efx->rx_queue[0];
+       while (rxdmaqs) {
+               if (rxdmaqs & 0x01)
+                       efx_fast_push_rx_descriptors(rx_queue);
+               rx_queue++;
+               rxdmaqs >>= 1;
+       }
+
+       return rx_quota;
+}
+
+/* Mark channel as finished processing
+ *
+ * Note that since we will not receive further interrupts for this
+ * channel before we finish processing and call the eventq_read_ack()
+ * method, there is no need to use the interrupt hold-off timers.
+ */
+static inline void efx_channel_processed(struct efx_channel *channel)
+{
+       /* Write to EVQ_RPTR_REG.  If a new event arrived in a race
+        * with finishing processing, a new interrupt will be raised.
+        */
+       channel->work_pending = 0;
+       smp_wmb(); /* Ensure channel updated before any new interrupt. */
+       falcon_eventq_read_ack(channel);
+}
+
+/* NAPI poll handler
+ *
+ * NAPI guarantees serialisation of polls of the same device, which
+ * provides the guarantee required by efx_process_channel().
+ */
+#if !defined(EFX_HAVE_OLD_NAPI)
+static int efx_poll(struct napi_struct *napi, int budget)
+{
+       struct efx_channel *channel =
+               container_of(napi, struct efx_channel, napi_str);
+       struct net_device *napi_dev = channel->napi_dev;
+#else
+static int efx_poll(struct net_device *napi, int *budget_ret)
+{
+       struct net_device *napi_dev = napi;
+       struct efx_channel *channel = napi_dev->priv;
+       int budget = min(napi_dev->quota, *budget_ret);
+#endif
+       int unused;
+       int rx_packets;
+
+       EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
+                 channel->channel, raw_smp_processor_id());
+
+       unused = efx_process_channel(channel, budget);
+       rx_packets = (budget - unused);
+#if defined(EFX_HAVE_OLD_NAPI)
+       napi_dev->quota -= rx_packets;
+       *budget_ret -= rx_packets;
+#endif
+
+       if (rx_packets < budget) {
+               /* There is no race here; although napi_disable() will
+                * only wait for netif_rx_complete(), this isn't a problem
+                * since efx_channel_processed() will have no effect if
+                * interrupts have already been disabled.
+                */
+               netif_rx_complete(napi_dev, napi);
+               efx_channel_processed(channel);
+       }
+
+#if !defined(EFX_HAVE_OLD_NAPI)
+       return rx_packets;
+#else
+       return (rx_packets >= budget);
+#endif
+}
+
+/* Process the eventq of the specified channel immediately on this CPU
+ *
+ * Disable hardware generated interrupts, wait for any existing
+ * processing to finish, then directly poll (and ack ) the eventq.
+ * Finally reenable NAPI and interrupts.
+ *
+ * Since we are touching interrupts the caller should hold the suspend lock
+ */
+void efx_process_channel_now(struct efx_channel *channel)
+{
+       struct efx_nic *efx = channel->efx;
+
+       BUG_ON(!channel->used_flags);
+       BUG_ON(!channel->enabled);
+
+       /* Disable interrupts and wait for ISRs to complete */
+       falcon_disable_interrupts(efx);
+       if (efx->legacy_irq)
+               synchronize_irq(efx->legacy_irq);
+       if (channel->has_interrupt && channel->irq)
+               synchronize_irq(channel->irq);
+
+       /* Wait for any NAPI processing to complete */
+       napi_disable(&channel->napi_str);
+
+       /* Poll the channel */
+       (void) efx_process_channel(channel, efx->type->evq_size);
+
+       /* Ack the eventq. This may cause an interrupt to be generated
+        * when they are reenabled */
+       efx_channel_processed(channel);
+
+       /* Reenable NAPI polling */
+       napi_enable(&channel->napi_str);
+
+       /* Reenable interrupts */
+       falcon_enable_interrupts(efx);
+}
+
+/* Create event queue
+ * Event queue memory allocations are done only once.  If the channel
+ * is reset, the memory buffer will be reused; this guards against
+ * errors during channel reset and also simplifies interrupt handling.
+ */
+static int efx_probe_eventq(struct efx_channel *channel)
+{
+       EFX_LOG(channel->efx, "chan %d create event queue\n", channel->channel);
+
+       return falcon_probe_eventq(channel);
+}
+
+/* Prepare channel's event queue */
+static int efx_init_eventq(struct efx_channel *channel)
+{
+       EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
+
+       ASSERT_RTNL();
+
+       /* Initialise fields */
+       channel->eventq_read_ptr = 0;
+
+       return falcon_init_eventq(channel);
+}
+
+static void efx_fini_eventq(struct efx_channel *channel)
+{
+       EFX_LOG(channel->efx, "chan %d fini event queue\n", channel->channel);
+
+       ASSERT_RTNL();
+
+       falcon_fini_eventq(channel);
+}
+
+static void efx_remove_eventq(struct efx_channel *channel)
+{
+       EFX_LOG(channel->efx, "chan %d remove event queue\n", channel->channel);
+
+       falcon_remove_eventq(channel);
+}
+
+/**************************************************************************
+ *
+ * Channel handling
+ *
+ *************************************************************************/
+
+/* Setup per-NIC RX buffer parameters.
+ * Calculate the rx buffer allocation parameters required to support
+ * the current MTU, including padding for header alignment and overruns.
+ */
+static void efx_calc_rx_buffer_params(struct efx_nic *efx)
+{
+       unsigned int order, len;
+
+       len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) +
+              EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
+              efx->type->rx_buffer_padding);
+
+       /* Page-based allocation page-order */
+       for (order = 0; ((1u << order) * PAGE_SIZE) < len; ++order)
+               ;
+
+       efx->rx_buffer_len = len;
+       efx->rx_buffer_order = order;
+}
+
+static int efx_probe_channel(struct efx_channel *channel)
+{
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+       int rc;
+
+       EFX_LOG(channel->efx, "creating channel %d\n", channel->channel);
+
+       rc = efx_probe_eventq(channel);
+       if (rc)
+               goto fail1;
+
+       efx_for_each_channel_tx_queue(tx_queue, channel) {
+               rc = efx_probe_tx_queue(tx_queue);
+               if (rc)
+                       goto fail2;
+       }
+
+       efx_for_each_channel_rx_queue(rx_queue, channel) {
+               rc = efx_probe_rx_queue(rx_queue);
+               if (rc)
+                       goto fail3;
+       }
+
+       channel->n_rx_frm_trunc = 0;
+
+       return 0;
+
+ fail3:
+       efx_for_each_channel_rx_queue(rx_queue, channel)
+               efx_remove_rx_queue(rx_queue);
+ fail2:
+       efx_for_each_channel_tx_queue(tx_queue, channel)
+               efx_remove_tx_queue(tx_queue);
+ fail1:
+       return rc;
+}
+
+
+/* Channels are shutdown and reinitialised whilst the NIC is running
+ * to propagate configuration changes (mtu, checksum offload), or
+ * to clear hardware error conditions
+ */
+static int efx_init_channels(struct efx_nic *efx)
+{
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+       struct efx_channel *channel;
+       int rc = 0;
+
+       /* Recalculate the rx buffer parameters */
+       efx_calc_rx_buffer_params(efx);
+
+       /* Initialise the channels */
+       efx_for_each_channel(channel, efx) {
+               EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
+
+               rc = efx_init_eventq(channel);
+               if (rc)
+                       goto err;
+
+               efx_for_each_channel_tx_queue(tx_queue, channel) {
+                       rc = efx_init_tx_queue(tx_queue);
+                       if (rc)
+                               goto err;
+               }
+
+               /* The rx buffer allocation strategy is MTU dependent */
+               efx_rx_strategy(channel);
+
+               efx_for_each_channel_rx_queue(rx_queue, channel) {
+                       rc = efx_init_rx_queue(rx_queue);
+                       if (rc)
+                               goto err;
+               }
+
+               WARN_ON(channel->rx_pkt != NULL);
+               efx_rx_strategy(channel);
+       }
+
+       return 0;
+
+ err:
+       EFX_ERR(efx, "failed to initialise channel %d\n",
+               channel ? channel->channel : -1);
+       efx_fini_channels(efx);
+       return rc;
+}
+
+/* This enables event queue processing and packet transmission.
+ *
+ * Note that this function is not allowed to fail, since that would
+ * introduce too much complexity into the suspend/resume path.
+ */
+static void efx_start_channel(struct efx_channel *channel)
+{
+       struct efx_rx_queue *rx_queue;
+
+       EFX_LOG(channel->efx, "starting chan %d\n", channel->channel);
+
+       if (!(channel->efx->net_dev->flags & IFF_UP))
+               netif_napi_add(channel->napi_dev, &channel->napi_str,
+                              efx_poll, napi_weight);
+
+       /* Mark channel as enabled */
+       channel->work_pending = 0;
+       channel->enabled = 1;
+       smp_wmb(); /* ensure channel updated before first interrupt */
+
+       /* Enable NAPI poll handler */
+       napi_enable(&channel->napi_str);
+
+       /* Load up RX descriptors */
+       efx_for_each_channel_rx_queue(rx_queue, channel)
+               efx_fast_push_rx_descriptors(rx_queue);
+}
+
+/* This disables event queue processing and packet transmission.
+ * This function does not guarantee that all queue processing
+ * (e.g. RX refill) is complete.
+ */
+static void efx_stop_channel(struct efx_channel *channel)
+{
+       struct efx_rx_queue *rx_queue;
+
+       if (!channel->enabled)
+               return;
+
+       EFX_LOG(channel->efx, "stop chan %d\n", channel->channel);
+
+       /* Mark channel as disabled */
+       channel->enabled = 0;
+
+       /* Wait for any NAPI processing to complete */
+       napi_disable(&channel->napi_str);
+
+       /* Ensure that any worker threads have exited or will be
+        * no-ops.
+        */
+       efx_for_each_channel_rx_queue(rx_queue, channel) {
+               spin_lock_bh(&rx_queue->add_lock);
+               spin_unlock_bh(&rx_queue->add_lock);
+       }
+}
+
+static void efx_fini_channels(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+
+       ASSERT_RTNL();
+
+       efx_for_each_channel(channel, efx) {
+               EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel);
+
+               efx_for_each_channel_rx_queue(rx_queue, channel)
+                       efx_fini_rx_queue(rx_queue);
+               efx_for_each_channel_tx_queue(tx_queue, channel)
+                       efx_fini_tx_queue(tx_queue);
+       }
+
+       /* Do the event queues last so that we can handle flush events
+        * for all DMA queues. */
+       efx_for_each_channel(channel, efx) {
+               EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel);
+
+               efx_fini_eventq(channel);
+       }
+}
+
+static void efx_remove_channel(struct efx_channel *channel)
+{
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+
+       EFX_LOG(channel->efx, "destroy chan %d\n", channel->channel);
+
+       efx_for_each_channel_rx_queue(rx_queue, channel)
+               efx_remove_rx_queue(rx_queue);
+       efx_for_each_channel_tx_queue(tx_queue, channel)
+               efx_remove_tx_queue(tx_queue);
+       efx_remove_eventq(channel);
+
+       channel->used_flags = 0;
+}
+
+/**************************************************************************
+ *
+ * Port handling
+ *
+ **************************************************************************/
+
+/* This ensures that the kernel is kept informed (via
+ * netif_carrier_on/off) of the link status, and also maintains the
+ * link status's stop on the port's TX queue.
+ */
+static void efx_link_status_changed(struct efx_nic *efx)
+{
+       unsigned long flags __attribute__ ((unused));
+       int carrier_ok;
+
+       /* Ensure no link status notifications get sent to the OS after the net
+        * device has been unregistered. */
+       if (!efx->net_dev_registered)
+               return;
+
+       carrier_ok = netif_carrier_ok(efx->net_dev) ? 1 : 0;
+       if (efx->link_up != carrier_ok) {
+               efx->n_link_state_changes++;
+
+               if (efx->link_up)
+                       netif_carrier_on(efx->net_dev);
+               else
+                       netif_carrier_off(efx->net_dev);
+       }
+
+       /* Inform driverlink client */
+       EFX_DL_CALLBACK(efx, link_change, efx->link_up);
+
+       /* Status message for kernel log */
+       if (efx->link_up) {
+               struct mii_if_info *gmii = &efx->mii;
+               unsigned adv, lpa;
+               /* NONE here means direct XAUI from the controller, with no
+                * MDIO-attached device we can query. */
+               if (efx->phy_type != PHY_TYPE_NONE) {
+                       adv = gmii_advertised(gmii);
+                       lpa = gmii_lpa(gmii);
+               } else {
+                       lpa = GM_LPA_10000 | LPA_DUPLEX;
+                       adv = lpa;
+               }
+               EFX_INFO(efx, "link up at %dMbps %s-duplex "
+                        "(adv %04x lpa %04x) (MTU %d)%s%s%s%s\n",
+                        (efx->link_options & GM_LPA_10000 ? 10000 :
+                         (efx->link_options & GM_LPA_1000 ? 1000 :
+                          (efx->link_options & GM_LPA_100 ? 100 :
+                           10))),
+                        (efx->link_options & GM_LPA_DUPLEX ?
+                         "full" : "half"),
+                        adv, lpa,
+                        efx->net_dev->mtu,
+                        (efx->loopback_mode ? " [" : ""),
+                        (efx->loopback_mode ? LOOPBACK_MODE(efx) : ""),
+                        (efx->loopback_mode ? " LOOPBACK]" : ""),
+                        (efx->promiscuous ? " [PROMISC]" : ""));
+       } else {
+               EFX_INFO(efx, "link down\n");
+       }
+
+}
+
+/* This call reinitialises the MAC to pick up new PHY settings
+ * To call from a context that cannot sleep use reconfigure_work work item
+ * For on_disabled=1 the caller must be serialised against efx_reset,
+ * ideally by holding the rtnl lock.
+ */
+void efx_reconfigure_port(struct efx_nic *efx, int on_disabled)
+{
+       mutex_lock(&efx->mac_lock);
+
+       EFX_LOG(efx, "reconfiguring MAC from PHY settings\n");
+
+       if (on_disabled)
+               ASSERT_RTNL();
+       else if (!efx->port_enabled)
+               goto out;
+
+       efx->mac_op->reconfigure(efx);
+
+out:
+       /* Inform kernel of loss/gain of carrier */
+       efx_link_status_changed(efx);
+
+       mutex_unlock(&efx->mac_lock);
+}
+
+static void efx_reconfigure_work(struct work_struct *data)
+{
+       struct efx_nic *efx = container_of(data, struct efx_nic,
+                                          reconfigure_work);
+
+       EFX_LOG(efx, "MAC reconfigure executing on CPU %d\n",
+               raw_smp_processor_id());
+
+       /* Reinitialise MAC to activate new PHY parameters */
+       efx_reconfigure_port(efx, 0);
+}
+
+static int efx_probe_port(struct efx_nic *efx)
+{
+       unsigned char *dev_addr;
+       int rc;
+
+       EFX_LOG(efx, "create port\n");
+
+       /* Connect up MAC/PHY operations table and read MAC address */
+       rc = falcon_probe_port(efx);
+       if (rc)
+               goto err;
+
+       /* Sanity check MAC address */
+       dev_addr = efx->mac_address;
+       if (!is_valid_ether_addr(dev_addr)) {
+               DECLARE_MAC_BUF(mac);
+
+               EFX_ERR(efx, "invalid MAC address %s\n",
+                       print_mac(mac, dev_addr));
+               if (!allow_bad_hwaddr) {
+                       rc = -EINVAL;
+                       goto err;
+               }
+               random_ether_addr(dev_addr);
+               EFX_INFO(efx, "using locally-generated MAC %s\n",
+                        print_mac(mac, dev_addr));
+       }
+
+       /* Register debugfs entries */
+       rc = efx_init_debugfs_port(efx);
+       if (rc)
+               goto err;
+
+       return 0;
+
+ err:
+       efx_remove_port(efx);
+       return rc;
+}
+
+static int efx_init_port(struct efx_nic *efx)
+{
+       int rc;
+
+       EFX_LOG(efx, "init port\n");
+
+       /* The default power state is ON */
+       efx->phy_powered = 1;
+
+       /* Initialise the MAC and PHY */
+       rc = efx->mac_op->init(efx);
+       if (rc)
+               return rc;
+
+       efx->port_initialized = 1;
+
+       /* Reconfigure port to program MAC registers */
+       efx->mac_op->reconfigure(efx);
+
+       return 0;
+}
+
+/* Allow efx_reconfigure_port() to run, and propagate delayed changes
+ * to the promiscuous flag to the MAC if needed */
+static void efx_start_port(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "start port\n");
+       ASSERT_RTNL();
+
+       BUG_ON(efx->port_enabled);
+
+       mutex_lock(&efx->mac_lock);
+       efx->port_enabled = 1;
+       mutex_unlock(&efx->mac_lock);
+
+       if (efx->net_dev_registered) {
+               int promiscuous;
+
+               netif_tx_lock_bh(efx->net_dev);
+               promiscuous = (efx->net_dev->flags & IFF_PROMISC) ? 1 : 0;
+               if (efx->promiscuous != promiscuous) {
+                       efx->promiscuous = promiscuous;
+                       queue_work(efx->workqueue, &efx->reconfigure_work);
+               }
+               netif_tx_unlock_bh(efx->net_dev);
+       }
+}
+
+/* Prevents efx_reconfigure_port() from executing, and prevents
+ * efx_set_multicast_list() from scheduling efx_reconfigure_work.
+ * efx_reconfigure_work can still be scheduled via NAPI processing
+ * until efx_flush_all() is called */
+static void efx_stop_port(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "stop port\n");
+       ASSERT_RTNL();
+
+       mutex_lock(&efx->mac_lock);
+       efx->port_enabled = 0;
+       mutex_unlock(&efx->mac_lock);
+
+       /* Serialise against efx_set_multicast_list() */
+       if (efx->net_dev_registered) {
+               netif_tx_lock_bh(efx->net_dev);
+               netif_tx_unlock_bh(efx->net_dev);
+       }
+}
+
+static void efx_fini_port(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "shut down port\n");
+
+       if (!efx->port_initialized)
+               return;
+
+       efx->mac_op->fini(efx);
+       efx->port_initialized = 0;
+
+       /* Mark the link down */
+       efx->link_up = 0;
+       efx_link_status_changed(efx);
+}
+
+static void efx_remove_port(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "destroying port\n");
+
+       efx_fini_debugfs_port(efx);
+       falcon_remove_port(efx);
+}
+
+/**************************************************************************
+ *
+ * NIC handling
+ *
+ **************************************************************************/
+
+/* This configures the PCI device to enable I/O and DMA. */
+static int efx_init_io(struct efx_nic *efx)
+{
+       struct pci_dev *pci_dev = efx->pci_dev;
+       int rc;
+
+       EFX_LOG(efx, "initialising I/O\n");
+
+       /* Generic device-enabling code */
+       rc = pci_enable_device(pci_dev);
+       if (rc) {
+               EFX_ERR(efx, "failed to enable PCI device\n");
+               goto fail1;
+       }
+
+       pci_set_master(pci_dev);
+
+       /* Set the PCI DMA mask.  Try all possibilities from our
+        * genuine mask down to 32 bits, because some architectures
+        * (e.g. x86_64 with iommu_sac_force set) will allow 40 bit
+        * masks event though they reject 46 bit masks.
+        */
+       efx->dma_mask = efx->type->max_dma_mask;
+       while (efx->dma_mask > 0x7fffffffUL) {
+               if (pci_dma_supported(pci_dev, efx->dma_mask) &&
+                   ((rc = pci_set_dma_mask(pci_dev, efx->dma_mask)) == 0))
+                       break;
+               efx->dma_mask >>= 1;
+       }
+       if (rc) {
+               EFX_ERR(efx, "could not find a suitable DMA mask\n");
+               goto fail2;
+       }
+       EFX_LOG(efx, "using DMA mask %llx\n",
+               (unsigned long long)efx->dma_mask);
+       rc = pci_set_consistent_dma_mask(pci_dev, efx->dma_mask);
+       if (rc) {
+               /* pci_set_consistent_dma_mask() is not *allowed* to
+                * fail with a mask that pci_set_dma_mask() accepted,
+                * but just in case...
+                */
+               EFX_ERR(efx, "failed to set consistent DMA mask\n");
+               goto fail2;
+       }
+
+       /* Get memory base address */
+       efx->membase_phys = pci_resource_start(efx->pci_dev,
+                                              efx->type->mem_bar);
+#if !defined(EFX_HAVE_MSIX_TABLE_RESERVED)
+       rc = pci_request_region(pci_dev, efx->type->mem_bar, "sfc");
+#else
+       if (!request_mem_region(efx->membase_phys, efx->type->mem_map_size,
+                               "sfc"))
+               rc = -EIO;
+#endif
+       if (rc) {
+               EFX_ERR(efx, "request for memory BAR failed\n");
+               rc = -EIO;
+               goto fail3;
+       }
+       efx->membase = ioremap_nocache(efx->membase_phys,
+                                      efx->type->mem_map_size);
+       if (!efx->membase) {
+               EFX_ERR(efx, "could not map memory BAR %d at %lx+%x\n",
+                       efx->type->mem_bar, efx->membase_phys,
+                       efx->type->mem_map_size);
+               rc = -ENOMEM;
+               goto fail4;
+       }
+       EFX_LOG(efx, "memory BAR %u at %lx+%x (virtual %p)\n",
+               efx->type->mem_bar, efx->membase_phys, efx->type->mem_map_size,
+               efx->membase);
+
+       return 0;
+
+ fail4:
+       release_mem_region(efx->membase_phys, efx->type->mem_map_size);
+ fail3:
+       efx->membase_phys = 0UL;
+       /* fall-thru */
+ fail2:
+       pci_disable_device(efx->pci_dev);
+ fail1:
+       return rc;
+}
+
+static void efx_fini_io(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "shutting down I/O\n");
+
+       if (efx->membase) {
+               iounmap(efx->membase);
+               efx->membase = NULL;
+       }
+
+       if (efx->membase_phys) {
+#if !defined(EFX_HAVE_MSIX_TABLE_RESERVED)
+               pci_release_region(efx->pci_dev, efx->type->mem_bar);
+#else
+               release_mem_region(efx->membase_phys, efx->type->mem_map_size);
+#endif
+               efx->membase_phys = 0UL;
+       }
+
+       pci_disable_device(efx->pci_dev);
+}
+
+/* Probe the number and type of interrupts we are able to obtain. */
+static int efx_probe_interrupts(struct efx_nic *efx)
+{
+       struct msix_entry xentries[EFX_MAX_CHANNELS];
+       int rc, i;
+
+       /* Select number of used RSS queues */
+       /* TODO: Can we react to CPU hotplug? */
+       if (rss_cpus == 0)
+               rss_cpus = num_online_cpus();
+
+       efx->rss_queues = 1;
+       if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
+               unsigned int max_channel = efx->type->phys_addr_channels - 1;
+
+               BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
+               efx->rss_queues = min(max_channel + 1, rss_cpus);
+               efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
+       }
+
+       /* Determine how many RSS queues we can use, and mark channels
+        * with the appropriate interrupt state */
+       if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
+               /* Build MSI request structure */
+               for (i = 0; i < efx->rss_queues; i++)
+                       xentries[i].entry = i;
+
+               /* Request maximum number of MSI interrupts */
+               rc = pci_enable_msix(efx->pci_dev, xentries, efx->rss_queues);
+               if (rc > 0) {
+                       EFX_BUG_ON_PARANOID(rc >= efx->rss_queues);
+                       efx->rss_queues = rc;
+                       rc = pci_enable_msix(efx->pci_dev, xentries,
+                                            efx->rss_queues);
+               }
+               if (rc == 0) {
+                       for (i = 0; i < efx->rss_queues; i++) {
+                               efx->channel[i].has_interrupt = 1;
+                               efx->channel[i].irq = xentries[i].vector;
+                       }
+               } else {
+                       /* Fall back to single channel MSI */
+                       efx->interrupt_mode = EFX_INT_MODE_MSI;
+                       EFX_ERR(efx, "could not enable MSI-X\n");
+               }
+       }
+
+       /* Try single interrupt MSI */
+       if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
+               efx->rss_queues = 1;
+               rc = pci_enable_msi(efx->pci_dev);
+               if (rc == 0) {
+                       efx->channel[0].irq = efx->pci_dev->irq;
+                       efx->channel[0].has_interrupt = 1;
+               } else {
+                       EFX_ERR(efx, "could not enable MSI\n");
+                       efx->interrupt_mode = EFX_INT_MODE_LEGACY;
+               }
+       }
+
+       /* Assume legacy interrupts */
+       if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
+               /* Every channel is interruptible */
+               for (i = 0; i < EFX_MAX_CHANNELS; i++)
+                       efx->channel[i].has_interrupt = 1;
+               efx->legacy_irq = efx->pci_dev->irq;
+       }
+
+       return 0;
+}
+
+static void efx_remove_interrupts(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+
+       /* Remove MSI/MSI-X interrupts */
+       efx_for_each_channel_with_interrupt(channel, efx)
+               channel->irq = 0;
+       pci_disable_msi(efx->pci_dev);
+       pci_disable_msix(efx->pci_dev);
+
+       /* Remove legacy interrupt */
+       efx->legacy_irq = 0;
+}
+
+/* Select number of used resources
+ * Should be called after probe_interrupts()
+ */
+static int efx_select_used(struct efx_nic *efx)
+{
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+       int i;
+
+       /* TX queues.  One per port per channel with TX capability
+        * (more than one per port won't work on Linux, due to out
+        *  of order issues... but will be fine on Solaris)
+        */
+       tx_queue = &efx->tx_queue[0];
+
+       /* Perform this for each channel with TX capabilities.
+        * At the moment, we only support a single TX queue
+        */
+       tx_queue->used = 1;
+       if ((!EFX_INT_MODE_USE_MSI(efx)) && separate_tx_and_rx_channels)
+               tx_queue->channel = &efx->channel[1];
+       else
+               tx_queue->channel = &efx->channel[0];
+       tx_queue->channel->used_flags |= EFX_USED_BY_TX;
+       tx_queue++;
+
+       /* RX queues.  Each has a dedicated channel. */
+       for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
+               rx_queue = &efx->rx_queue[i];
+
+               if (i < efx->rss_queues) {
+                       rx_queue->used = 1;
+                       /* If we allow multiple RX queues per channel
+                        * we need to decide that here
+                        */
+                       rx_queue->channel = &efx->channel[rx_queue->queue];
+                       rx_queue->channel->used_flags |= EFX_USED_BY_RX;
+                       rx_queue++;
+               }
+       }
+       return 0;
+}
+
+static int efx_probe_nic(struct efx_nic *efx)
+{
+       int rc;
+
+       EFX_LOG(efx, "creating NIC\n");
+
+       /* Carry out hardware-type specific initialisation */
+       rc = falcon_probe_nic(efx);
+       if (rc)
+               goto fail1;
+
+       /* Determine the number of channels and RX queues by trying to hook
+        * in MSI-X interrupts. */
+       rc = efx_probe_interrupts(efx);
+       if (rc)
+               goto fail2;
+
+       /* Determine number of RX queues and TX queues */
+       rc = efx_select_used(efx);
+       if (rc)
+               goto fail3;
+
+       /* Register debugfs entries */
+       rc = efx_init_debugfs_nic(efx);
+       if (rc)
+               goto fail4;
+       /* Initialise the interrupt moderation settings */
+       efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
+
+       return 0;
+
+ fail4:
+       /* fall-thru */
+ fail3:
+       efx_remove_interrupts(efx);
+ fail2:
+       falcon_remove_nic(efx);
+ fail1:
+       return rc;
+}
+
+static void efx_remove_nic(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "destroying NIC\n");
+
+       efx_remove_interrupts(efx);
+       falcon_remove_nic(efx);
+
+       efx_fini_debugfs_nic(efx);
+}
+
+/**************************************************************************
+ *
+ * NIC startup/shutdown
+ *
+ *************************************************************************/
+
+static int efx_probe_all(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+       int rc;
+
+       /* Create NIC */
+       rc = efx_probe_nic(efx);
+       if (rc) {
+               EFX_ERR(efx, "failed to create NIC\n");
+               goto fail1;
+       }
+
+       /* Create port */
+       rc = efx_probe_port(efx);
+       if (rc) {
+               EFX_ERR(efx, "failed to create port\n");
+               goto fail2;
+       }
+
+       /* Create channels */
+       efx_for_each_channel(channel, efx) {
+               rc = efx_probe_channel(channel);
+               if (rc) {
+                       EFX_ERR(efx, "failed to create channel %d\n",
+                               channel->channel);
+                       goto fail3;
+               }
+       }
+
+       return 0;
+
+ fail3:
+       efx_for_each_channel(channel, efx)
+               efx_remove_channel(channel);
+ fail2:
+       efx_remove_port(efx);
+ fail1:
+       return rc;
+}
+
+/* Called after previous invocation(s) of efx_stop_all, restarts the
+ * port, kernel transmit queue, NAPI processing and hardware interrupts.
+ * This function is safe to call multiple times when the NIC is in any
+ * state. */
+static void efx_start_all(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+
+       ASSERT_RTNL();
+
+       /* Check that it is appropriate to restart the interface. All
+        * of these flags are safe to read under just the rtnl lock */
+       if (efx->port_enabled)
+               return;
+       if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT))
+               return;
+       if (efx->net_dev_registered && !netif_running(efx->net_dev))
+               return;
+
+       /* Mark the port as enabled so port reconfigurations can start, then
+        * restart the transmit interface early so the watchdog timer stops */
+       efx_start_port(efx);
+       efx_wake_queue(efx);
+
+       efx_for_each_channel(channel, efx)
+               efx_start_channel(channel);
+
+       falcon_enable_interrupts(efx);
+
+       /* Start hardware monitor if we're in RUNNING */
+       if (efx->state == STATE_RUNNING)
+               queue_delayed_work(efx->workqueue, &efx->monitor_work,
+                                  efx_monitor_interval);
+}
+
+/* Flush all delayed work. Should only be called when no more delayed work
+ * will be scheduled. This doesn't flush pending online resets (efx_reset),
+ * since we're holding the rtnl_lock at this point. */
+static void efx_flush_all(struct efx_nic *efx)
+{
+#if defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+       struct efx_rx_queue *rx_queue;
+
+       /* Make sure the hardware monitor is stopped */
+       cancel_delayed_work_sync(&efx->monitor_work);
+
+       /* Ensure that all RX slow refills are complete. */
+       efx_for_each_rx_queue(rx_queue, efx) {
+               cancel_delayed_work_sync(&rx_queue->work);
+       }
+#endif
+
+#if defined(EFX_USE_CANCEL_WORK_SYNC)
+       /* Stop scheduled port reconfigurations */
+       cancel_work_sync(&efx->reconfigure_work);
+#endif
+
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+       /* Ensure that the hardware monitor and asynchronous port
+        * reconfigurations are complete, which are the only two consumers
+        * of efx->workqueue. Since the hardware monitor runs on a long period,
+        * we put in some effort to cancel the delayed work safely rather
+        * than just flushing the queue twice (which is guaranteed to flush
+        * all the work since both efx_monitor and efx_reconfigure_work disarm
+        * if !efx->port_enabled. */
+       if (timer_pending(&efx->monitor_work.timer))
+               cancel_delayed_work(&efx->monitor_work);
+       flush_workqueue(efx->workqueue);
+       if (timer_pending(&efx->monitor_work.timer))
+               cancel_delayed_work(&efx->monitor_work);
+       flush_workqueue(efx->workqueue);
+
+       /* efx_rx_work will disarm if !channel->enabled, so we can just
+        * flush the refill workqueue twice as well. */
+       flush_workqueue(efx->refill_workqueue);
+       flush_workqueue(efx->refill_workqueue);
+#endif
+}
+
+/* Quiesce hardware and software without bringing the link down.
+ * Safe to call multiple times, when the nic and interface is in any
+ * state. The caller is guaranteed to subsequently be in a position
+ * to modify any hardware and software state they see fit without
+ * taking locks. */
+static void efx_stop_all(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+
+       ASSERT_RTNL();
+
+       /* port_enabled can be read safely under the rtnl lock */
+       if (!efx->port_enabled)
+               return;
+
+       /* Disable interrupts and wait for ISR to complete */
+       falcon_disable_interrupts(efx);
+       if (efx->legacy_irq)
+               synchronize_irq(efx->legacy_irq);
+       efx_for_each_channel_with_interrupt(channel, efx)
+               if (channel->irq)
+                       synchronize_irq(channel->irq);
+
+       /* Stop all synchronous port reconfigurations. */
+       efx_stop_port(efx);
+
+       /* Stop all NAPI processing and synchronous rx refills */
+       efx_for_each_channel(channel, efx)
+               efx_stop_channel(channel);
+
+       /* Flush reconfigure_work, refill_workqueue, monitor_work */
+       efx_flush_all(efx);
+
+       /* Stop the kernel transmit interface late, so the watchdog
+        * timer isn't ticking over the flush */
+       efx_stop_queue(efx);
+       if (efx->net_dev_registered) {
+               netif_tx_lock_bh(efx->net_dev);
+               netif_tx_unlock_bh(efx->net_dev);
+       }
+}
+
+static void efx_remove_all(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+
+       efx_for_each_channel(channel, efx)
+               efx_remove_channel(channel);
+       efx_remove_port(efx);
+       efx_remove_nic(efx);
+}
+
+static int efx_run_selftests(struct efx_nic *efx)
+{
+       struct efx_self_tests tests;
+       unsigned modes = efx->startup_loopbacks & efx->loopback_modes;
+       int rc;
+
+       rc = efx_online_test(efx, &tests);
+       if (rc) {
+               EFX_ERR(efx, "failed self-tests with interrupt_mode of %s\n",
+                       INT_MODE(efx));
+               goto fail;
+       }
+
+       if (onload_offline_selftest && modes) {
+               /* Run offline self test */
+               EFX_LOG(efx, "performing on-load offline self-tests\n");
+               rc = efx_offline_test(efx, &tests, modes);
+               EFX_LOG(efx, "%s on-load offline self-tests\n",
+                       rc ? "FAILED" : "PASSED");
+               if (rc)
+                       goto fail;
+       }
+
+       return 0;
+
+ fail:
+       EFX_ERR(efx, "self-tests failed. Given up!\n");
+       if (allow_load_on_failure)
+               rc = 0;
+
+       return rc;
+}
+
+int efx_flush_queues(struct efx_nic *efx)
+{
+       int rc;
+
+       ASSERT_RTNL();
+
+       efx_stop_all(efx);
+
+       /* We can't just flush the tx queues because the event queues
+        * may contain tx completions from that queue. Just flush everything */
+       efx_fini_channels(efx);
+       rc = efx_init_channels(efx);
+       if (rc) {
+               efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+               return rc;
+       }
+
+       efx_start_all(efx);
+
+       return 0;
+}
+
+/**************************************************************************
+ *
+ * Interrupt moderation
+ *
+ **************************************************************************/
+
+/* Set interrupt moderation parameters */
+void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
+{
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+
+       ASSERT_RTNL();
+
+       efx_for_each_tx_queue(tx_queue, efx)
+               tx_queue->channel->irq_moderation = tx_usecs;
+
+       efx_for_each_rx_queue(rx_queue, efx)
+               rx_queue->channel->irq_moderation = rx_usecs;
+}
+
+/**************************************************************************
+ *
+ * Hardware monitor
+ *
+ **************************************************************************/
+
+/* Run periodically off the general workqueue. Serialised against
+ * efx_reconfigure_port via the mac_lock */
+static void efx_monitor(struct work_struct *data)
+{
+#if !defined(EFX_NEED_WORK_API_WRAPPERS)
+       struct efx_nic *efx = container_of(data, struct efx_nic,
+                                          monitor_work.work);
+#else
+       struct efx_nic *efx = container_of(data, struct efx_nic,
+                                          monitor_work);
+#endif
+       int rc = 0;
+
+       EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
+                 raw_smp_processor_id());
+
+
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+       /* Without cancel_delayed_work_sync(), we have to make sure that
+        * we don't rearm when port_enabled == 0 */
+       mutex_lock(&efx->mac_lock);
+       if (!efx->port_enabled) {
+               mutex_unlock(&efx->mac_lock);
+               return;
+       }
+
+       rc = efx->mac_op->check_hw(efx);
+#else
+       /* If the mac_lock is already held then it is likely a port
+        * reconfiguration is already in place, which will likely do
+        * most of the work of check_hw() anyway. */
+       if (!mutex_trylock(&efx->mac_lock)) {
+               queue_delayed_work(efx->workqueue, &efx->monitor_work,
+                                  efx_monitor_interval);
+               return;
+       }
+
+       if (efx->port_enabled)
+               rc = efx->mac_op->check_hw(efx);
+#endif
+       mutex_unlock(&efx->mac_lock);
+
+       if (rc) {
+               if (monitor_reset) {
+                       EFX_ERR(efx, "hardware monitor detected a fault: "
+                               "triggering reset\n");
+                       efx_schedule_reset(efx, RESET_TYPE_MONITOR);
+               } else {
+                       EFX_ERR(efx, "hardware monitor detected a fault, "
+                               "skipping reset\n");
+               }
+       }
+
+       queue_delayed_work(efx->workqueue, &efx->monitor_work,
+                          efx_monitor_interval);
+}
+
+/**************************************************************************
+ *
+ * ioctls
+ *
+ *************************************************************************/
+
+/* Net device ioctl
+ * Context: process, rtnl_lock() held.
+ */
+static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
+{
+       struct efx_nic *efx = net_dev->priv;
+       int rc;
+
+       ASSERT_RTNL();
+
+       switch (cmd) {
+       case SIOCGMIIPHY:
+       case SIOCGMIIREG:
+               rc = generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL);
+               break;
+       case SIOCSMIIREG:
+               rc = generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL);
+               efx_reconfigure_port(efx, 0);
+               break;
+       default:
+               rc = -EOPNOTSUPP;
+       }
+
+       return rc;
+}
+
+/**************************************************************************
+ *
+ * NAPI interface
+ *
+ **************************************************************************/
+
+/* Allocate the NAPI dev's.
+ * Called after we know how many channels there are.
+ */
+static int efx_init_napi(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+       int rc;
+
+       ASSERT_RTNL();
+
+       /* Allocate the NAPI dev for the port */
+       efx->net_dev = alloc_etherdev(0);
+       if (!efx->net_dev) {
+               rc = -ENOMEM;
+               goto err;
+       }
+       efx->net_dev->priv = efx;
+       efx->mii.dev = efx->net_dev;
+
+       /* Set features based on module parameters and DMA mask.
+        * Enable DMA to ZONE_HIGHMEM if the NIC can access all memory
+        * directly.  This only has an effect on 32-bit systems and
+        * PAE on x86 limits memory to 64GB so 40 bits is plenty to
+        * address everything.  If the device can't address 40 bits
+        * then it's safest to turn NETIF_F_HIGHDMA off because this
+        * might be a PAE system with more than 4G of RAM and a 32-bit
+        * NIC.  The use of EFX_DMA_MASK is to eliminate compiler
+        * warnings on platforms where dma_addr_t is 32-bit.  We
+        * assume that in those cases we can access all memory
+        * directly if our DMA mask is all ones. */
+       efx->net_dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+       if (efx->dma_mask >= EFX_DMA_MASK(DMA_40BIT_MASK))
+               efx->net_dev->features |= NETIF_F_HIGHDMA;
+
+       /* Copy MAC address */
+       memcpy(&efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
+
+       /* Allocate the per channel devs */
+       efx_for_each_channel(channel, efx) {
+#if !defined(EFX_HAVE_OLD_NAPI)
+               channel->napi_dev = efx->net_dev;
+#else
+               channel->napi_dev = alloc_etherdev(0);
+               if (!channel->napi_dev) {
+                       rc = -ENOMEM;
+                       goto err;
+               }
+               channel->napi_dev->priv = channel;
+               atomic_set(&channel->napi_dev->refcnt, 1);
+#endif
+       }
+
+       return 0;
+ err:
+       efx_fini_napi(efx);
+       return rc;
+}
+
+/* Free the NAPI state for the port and channels */
+static void efx_fini_napi(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+
+       ASSERT_RTNL();
+
+       efx_for_each_channel(channel, efx) {
+               /* Finish per channel NAPI */
+#if defined(EFX_HAVE_OLD_NAPI)
+               if (channel->napi_dev) {
+                       channel->napi_dev->priv = NULL;
+                       free_netdev(channel->napi_dev);
+               }
+#endif
+               channel->napi_dev = NULL;
+       }
+
+       /* Finish port NAPI */
+       if (efx->net_dev) {
+               efx->net_dev->priv = NULL;
+               free_netdev(efx->net_dev);
+               efx->net_dev = NULL;
+       }
+}
+
+/**************************************************************************
+ *
+ * Kernel netpoll interface
+ *
+ *************************************************************************/
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/* Although in the common case interrupts will be disabled, this is not
+ * guaranteed. However, all our work happens inside the NAPI callback,
+ * so no locking is required.
+ */
+static void efx_netpoll(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct efx_channel *channel;
+
+       efx_for_each_channel_with_interrupt(channel, efx)
+               efx_schedule_channel(channel);
+}
+
+#endif
+
+/**************************************************************************
+ *
+ * Kernel net device interface
+ *
+ *************************************************************************/
+
+/* Context: process, rtnl_lock() held. */
+static int efx_net_open(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+       ASSERT_RTNL();
+
+       EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
+               raw_smp_processor_id());
+       efx_start_all(efx);
+       return 0;
+}
+
+/* Context: process, rtnl_lock() held.
+ * Note that the kernel will ignore our return code; this method
+ * should really be a void.
+ */
+static int efx_net_stop(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+       int rc;
+
+       EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
+               raw_smp_processor_id());
+
+       /* Stop device and flush all the channels */
+       efx_stop_all(efx);
+       efx_fini_channels(efx);
+       rc = efx_init_channels(efx);
+       if (rc)
+               efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+
+       return 0;
+}
+
+/* Context: process, dev_base_lock held, non-blocking.
+ * Statistics are taken directly from the MAC.
+ */
+static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct efx_mac_stats *mac_stats = &efx->mac_stats;
+       struct net_device_stats *stats = &efx->stats;
+
+       if (!spin_trylock(&efx->stats_lock))
+               return stats;
+       if (efx->state == STATE_RUNNING)
+               efx->mac_op->update_stats(efx);
+       spin_unlock(&efx->stats_lock);
+
+       stats->rx_packets = mac_stats->rx_packets;
+       stats->tx_packets = mac_stats->tx_packets;
+       stats->rx_bytes = mac_stats->rx_bytes;
+       stats->tx_bytes = mac_stats->tx_bytes;
+       stats->tx_errors = mac_stats->tx_bad;
+       stats->multicast = mac_stats->rx_multicast;
+       stats->collisions = mac_stats->tx_collision;
+       stats->rx_length_errors = mac_stats->rx_gtjumbo;
+       stats->rx_over_errors = mac_stats->rx_overflow;
+       stats->rx_crc_errors = mac_stats->rx_bad;
+       stats->rx_frame_errors = mac_stats->rx_align_error;
+       stats->rx_fifo_errors = 0;
+       stats->rx_missed_errors = mac_stats->rx_missed;
+       stats->rx_errors = (stats->rx_length_errors +
+                           stats->rx_over_errors +
+                           stats->rx_crc_errors +
+                           stats->rx_frame_errors +
+                           stats->rx_fifo_errors +
+                           stats->rx_missed_errors +
+                           mac_stats->rx_symbol_error);
+       stats->tx_aborted_errors = 0;
+       stats->tx_carrier_errors = 0;
+       stats->tx_fifo_errors = 0;
+       stats->tx_heartbeat_errors = 0;
+       stats->tx_window_errors = 0;
+
+       return stats;
+}
+
+/* Context: netif_tx_lock held, BHs disabled. */
+static void efx_watchdog(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d: %s\n",
+               atomic_read(&efx->netif_stop_count), efx->port_enabled,
+               monitor_reset ? "resetting channels" : "skipping reset");
+
+       if (monitor_reset)
+               efx_schedule_reset(efx, RESET_TYPE_MONITOR);
+}
+
+
+/* Context: process, rtnl_lock() held. */
+static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
+{
+       struct efx_nic *efx = net_dev->priv;
+       int rc = 0;
+
+       ASSERT_RTNL();
+
+       if (new_mtu > EFX_MAX_MTU)
+               return -EINVAL;
+
+       efx_stop_all(efx);
+
+       /* Ask driverlink client if we can change MTU */
+       rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu);
+       if (rc) {
+               EFX_ERR(efx, "MTU change vetoed by driverlink %s driver\n",
+                       efx->dl_cb_dev.request_mtu->driver->name);
+               goto out;
+       }
+
+       EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
+
+       efx_fini_channels(efx);
+       net_dev->mtu = new_mtu;
+       rc = efx_init_channels(efx);
+       if (rc)
+               goto fail;
+
+       /* Reconfigure the MAC */
+       efx_reconfigure_port(efx, 1);
+
+       /* Notify driverlink client of new MTU */
+       EFX_DL_CALLBACK(efx, mtu_changed, new_mtu);
+
+       efx_start_all(efx);
+
+ out:
+       return rc;
+
+ fail:
+       efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+       return rc;
+}
+
+static int efx_set_mac_address(struct net_device *net_dev, void *data)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct sockaddr *addr = data;
+       char *new_addr = addr->sa_data;
+
+       ASSERT_RTNL();
+
+       if (!is_valid_ether_addr(new_addr)) {
+               DECLARE_MAC_BUF(mac);
+               EFX_ERR(efx, "invalid ethernet MAC address requested: %s\n",
+                       print_mac(mac, new_addr));
+               return -EINVAL;
+       }
+
+       memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
+
+       /* Reconfigure the MAC */
+       efx_reconfigure_port(efx, 1);
+
+       return 0;
+}
+
+/* Context: netif_tx_lock held, BHs disabled. */
+static void efx_set_multicast_list(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct dev_mc_list *mc_list = net_dev->mc_list;
+       union efx_multicast_hash *mc_hash = &efx->multicast_hash;
+       unsigned long flags __attribute__ ((unused));
+       int promiscuous;
+       u32 crc;
+       int bit;
+       int i;
+
+       /* Set per-MAC promiscuity flag and reconfigure MAC if necessary */
+       promiscuous = (net_dev->flags & IFF_PROMISC) ? 1 : 0;
+       if (efx->promiscuous != promiscuous) {
+               if (efx->port_enabled) {
+                       efx->promiscuous = promiscuous;
+                       queue_work(efx->workqueue, &efx->reconfigure_work);
+               }
+       }
+
+       /* Build multicast hash table */
+       if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
+               memset(mc_hash, 0xff, sizeof(*mc_hash));
+       } else {
+               memset(mc_hash, 0x00, sizeof(*mc_hash));
+               for (i = 0; i < net_dev->mc_count; i++) {
+                       crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr);
+                       bit = (crc & ((1 << EFX_MCAST_HASH_BITS) - 1));
+                       set_bit_le(bit, (void *)mc_hash);
+                       mc_list = mc_list->next;
+               }
+       }
+
+       /* Create and activate new global multicast hash table */
+       falcon_set_multicast_hash(efx);
+}
+
+/* Handle net device notifier events */
+static int efx_netdev_event(struct notifier_block *this,
+                           unsigned long event, void *ptr)
+{
+       struct net_device *net_dev = (struct net_device *)ptr;
+
+       if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) {
+               struct efx_nic *efx = net_dev->priv;
+
+               strcpy(efx->name, net_dev->name);
+               efx_fini_debugfs_netdev(net_dev);
+               efx_init_debugfs_netdev(net_dev);
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block efx_netdev_notifier = {
+       .notifier_call = efx_netdev_event,
+};
+
+static int efx_register_netdev(struct efx_nic *efx)
+{
+       struct net_device *net_dev = efx->net_dev;
+       int rc;
+
+       net_dev->watchdog_timeo = 5 * HZ;
+       net_dev->irq = efx->pci_dev->irq;
+       net_dev->open = efx_net_open;
+       net_dev->stop = efx_net_stop;
+       net_dev->get_stats = efx_net_stats;
+       net_dev->tx_timeout = &efx_watchdog;
+       net_dev->hard_start_xmit = efx_hard_start_xmit;
+       net_dev->do_ioctl = efx_ioctl;
+       net_dev->change_mtu = efx_change_mtu;
+       net_dev->set_mac_address = efx_set_mac_address;
+       net_dev->set_multicast_list = efx_set_multicast_list;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       net_dev->poll_controller = efx_netpoll;
+#endif
+       SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
+       SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
+
+       /* Always start with carrier off; PHY events will detect the link */
+       netif_carrier_off(efx->net_dev);
+
+       BUG_ON(efx->net_dev_registered);
+
+       /* Clear MAC statistics */
+       efx->mac_op->update_stats(efx);
+       memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
+
+       rc = register_netdev(net_dev);
+       if (rc) {
+               EFX_ERR(efx, "could not register net dev\n");
+               return rc;
+       }
+       strcpy(efx->name, net_dev->name);
+
+       /* Create debugfs symlinks */
+       rc = efx_init_debugfs_netdev(net_dev);
+       if (rc) {
+               EFX_ERR(efx, "failed to init net dev debugfs\n");
+               unregister_netdev(efx->net_dev);
+               return rc;
+       }
+
+       /* Allow link change notifications to be sent to the operating
+        * system.  The must happen after register_netdev so that
+        * there are no outstanding link changes if that call fails.
+        * It must happen before efx_reconfigure_port so that the
+        * initial state of the link is reported. */
+       mutex_lock(&efx->mac_lock);
+       efx->net_dev_registered = 1;
+       mutex_unlock(&efx->mac_lock);
+
+       /* Safety net: in case we don't get a PHY event */
+       rtnl_lock();
+       efx_reconfigure_port(efx, 1);
+       rtnl_unlock();
+
+       EFX_LOG(efx, "registered\n");
+
+       return 0;
+}
+
+static void efx_unregister_netdev(struct efx_nic *efx)
+{
+       int was_registered = efx->net_dev_registered;
+       struct efx_tx_queue *tx_queue;
+
+       if (!efx->net_dev)
+               return;
+
+       BUG_ON(efx->net_dev->priv != efx);
+
+       /* SFC Bug 5356: Ensure that no more link status notifications get
+        * sent to the stack.  Bad things happen if there's an
+        * outstanding notification after the net device is freed, but
+        * they only get flushed out by unregister_netdev, not by
+        * free_netdev. */
+       mutex_lock(&efx->mac_lock);
+       efx->net_dev_registered = 0;
+       mutex_unlock(&efx->mac_lock);
+
+       /* Free up any skbs still remaining. This has to happen before
+        * we try to unregister the netdev as running their destructors
+        * may be needed to get the device ref. count to 0. */
+       efx_for_each_tx_queue(tx_queue, efx)
+               efx_release_tx_buffers(tx_queue);
+
+       if (was_registered) {
+               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+               efx_fini_debugfs_netdev(efx->net_dev);
+               unregister_netdev(efx->net_dev);
+       }
+}
+
+/**************************************************************************
+ *
+ * Device reset and suspend
+ *
+ **************************************************************************/
+
+/* This suspends the device (and acquires the suspend lock) without
+ * flushing the descriptor queues.  It is included for the convenience
+ * of the driverlink layer.
+ */
+void efx_suspend(struct efx_nic *efx)
+{
+       EFX_LOG(efx, "suspending operations\n");
+
+       down(&efx->suspend_lock);
+
+       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();
+
+       up(&efx->suspend_lock);
+}
+
+/* The final hardware and software finalisation before reset.
+ * This function does not handle serialisation with the kernel, it
+ * assumes the caller has done this */
+static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+       int rc;
+
+       ASSERT_RTNL();
+
+       rc = efx->mac_op->get_settings(efx, ecmd);
+       if (rc) {
+               EFX_ERR(efx, "could not back up PHY settings\n");
+               goto fail;
+       }
+
+       efx_fini_channels(efx);
+       return 0;
+
+ fail:
+       return rc;
+}
+
+/* The first part of software initialisation after a hardware reset
+ * This function does not handle serialisation with the kernel, it
+ * assumes the caller has done this */
+static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+       int rc;
+
+       rc = efx_init_channels(efx);
+       if (rc)
+               goto fail1;
+
+       /* In an INVISIBLE_RESET there might not be a link state transition,
+        * so we push the multicast list here. */
+       falcon_set_multicast_hash(efx);
+
+       /* Restore MAC and PHY settings. */
+       rc = efx->mac_op->set_settings(efx, ecmd);
+       if (rc) {
+               EFX_ERR(efx, "could not restore PHY settings\n");
+               goto fail2;
+       }
+
+       return 0;
+
+ fail2:
+       efx_fini_channels(efx);
+ fail1:
+       return rc;
+}
+
+/* Reset the NIC as transparently as possible. Do not reset the PHY
+ * Note that the reset may fail, in which case the card will be left
+ * in a most-probably-unusable state.
+ *
+ * This function will sleep.  You cannot reset from within an atomic
+ * state; use efx_schedule_reset() instead.
+ */
+static int efx_reset(struct efx_nic *efx)
+{
+       struct ethtool_cmd ecmd;
+       unsigned long flags __attribute__ ((unused));
+       enum reset_type method = efx->reset_pending;
+       int rc;
+
+       efx_dl_reset_lock();
+
+       rc = down_interruptible(&efx->suspend_lock);
+       if (rc) {
+               EFX_ERR(efx, "reset aborted by signal\n");
+               goto unlock_dl_lock;
+       }
+
+       /* We've got suspend_lock, which means we can only be in
+        * STATE_RUNNING or STATE_FINI. Don't clear
+        * efx->reset_pending, since this flag indicates that we
+        * should retry device initialisation.
+        */
+       if (efx->state != STATE_RUNNING) {
+               EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
+               goto unlock_suspend_lock;
+       }
+
+       /* Notify driverlink clients of imminent reset. */
+       efx_dl_reset_suspend(efx);
+       rtnl_lock();
+
+       efx->state = STATE_RESETTING;
+       EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));
+
+       /* The net_dev->get_stats handler is quite slow, and will fail
+        * if a fetch is pending over reset. Serialise against it. */
+       spin_lock(&efx->stats_lock);
+       spin_unlock(&efx->stats_lock);
+
+       efx_stop_all(efx);
+       mutex_lock(&efx->mac_lock);
+
+       rc = efx_reset_down(efx, &ecmd);
+       if (rc)
+               goto fail1;
+       falcon_fini_nic(efx);
+
+       rc = falcon_reset_hw(efx, method);
+       if (rc) {
+               EFX_ERR(efx, "failed to reset hardware\n");
+               goto fail2;
+       }
+
+       /* Allow resets to be rescheduled. */
+       efx->reset_pending = RESET_TYPE_NONE;
+
+       /* Reinitialise bus-mastering, which may have been turned off before
+        * the reset was scheduled. This is still appropriate, even in the
+        * RESET_TYPE_DISABLE since this driver generally assumes the hardware
+        * can respond to requests. */
+       pci_set_master(efx->pci_dev);
+
+       /* Reinitialise device. This is appropriate in the RESET_TYPE_DISABLE
+        * case so the driver can talk to external SRAM */
+       rc = falcon_init_nic(efx);
+       if (rc) {
+               EFX_ERR(efx, "failed to initialise NIC\n");
+               goto fail3;
+       }
+
+       /* Leave device stopped if necessary */
+       if (method == RESET_TYPE_DISABLE) {
+               /* Reinitialise the device anyway so the driver unload sequence
+                * can talk to the external SRAM */
+               (void) falcon_init_nic(efx);
+               rc = -EIO;
+               goto fail4;
+       }
+
+       rc = efx_reset_up(efx, &ecmd);
+       if (rc)
+               goto fail5;
+
+       mutex_unlock(&efx->mac_lock);
+       efx_reconfigure_port(efx, 1);
+       EFX_LOG(efx, "reset complete\n");
+
+       efx->state = STATE_RUNNING;
+       efx_start_all(efx);
+
+       rtnl_unlock();
+
+       goto notify;
+
+ fail5:
+ fail4:
+ fail3:
+ fail2:
+ fail1:
+       EFX_ERR(efx, "has been disabled\n");
+       efx->state = STATE_DISABLED;
+
+       /* Remove the net_dev */
+       mutex_unlock(&efx->mac_lock);
+       rtnl_unlock();
+       efx_unregister_netdev(efx);
+       efx_fini_port(efx);
+
+ notify:
+       /* Notify driverlink clients of completed reset */
+       efx_dl_reset_resume(efx, (rc == 0));
+
+ unlock_suspend_lock:
+       up(&efx->suspend_lock);
+
+ unlock_dl_lock:
+       efx_dl_reset_unlock();
+
+       return rc;
+}
+
+/* The worker thread exists so that code that cannot sleep can
+ * schedule a reset for later.
+ */
+static void efx_reset_work(struct work_struct *data)
+{
+       struct efx_nic *nic = container_of(data, struct efx_nic, reset_work);
+
+       efx_reset(nic);
+}
+
+void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
+{
+       enum reset_type method;
+
+       if (efx->reset_pending != RESET_TYPE_NONE) {
+               EFX_INFO(efx, "quenching already scheduled reset\n");
+               return;
+       }
+
+       switch (type) {
+       case RESET_TYPE_INVISIBLE:
+       case RESET_TYPE_ALL:
+       case RESET_TYPE_WORLD:
+       case RESET_TYPE_DISABLE:
+               method = type;
+               break;
+       case RESET_TYPE_RX_RECOVERY:
+       case RESET_TYPE_RX_DESC_FETCH:
+       case RESET_TYPE_TX_DESC_FETCH:
+               method = RESET_TYPE_INVISIBLE;
+               break;
+       default:
+               method = RESET_TYPE_ALL;
+               break;
+       }
+
+       if (method != type)
+               EFX_LOG(efx, "scheduling %s reset for %s\n",
+                       RESET_TYPE(method), RESET_TYPE(type));
+       else
+               EFX_LOG(efx, "scheduling %s reset\n", RESET_TYPE(method));
+
+       efx->reset_pending = method;
+
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+       queue_work(efx->reset_workqueue, &efx->reset_work);
+#else
+       queue_work(efx->workqueue, &efx->reset_work);
+#endif
+}
+
+/**************************************************************************
+ *
+ * List of NICs we support
+ *
+ **************************************************************************/
+
+enum efx_type_index {
+       EFX_TYPE_FALCON_A = 0,
+       EFX_TYPE_FALCON_B = 1,
+};
+
+static struct efx_nic_type *efx_nic_types[] = {
+       [EFX_TYPE_FALCON_A] = &falcon_a_nic_type,
+       [EFX_TYPE_FALCON_B] = &falcon_b_nic_type,
+};
+
+
+/* PCI device ID table */
+static struct pci_device_id efx_pci_table[] __devinitdata = {
+       {EFX_VENDID_SFC, FALCON_A_P_DEVID, PCI_ANY_ID, PCI_ANY_ID,
+        0, 0, EFX_TYPE_FALCON_A},
+       {EFX_VENDID_SFC, FALCON_B_P_DEVID, PCI_ANY_ID, PCI_ANY_ID,
+        0, 0, EFX_TYPE_FALCON_B},
+       {0}                     /* end of list */
+};
+
+/**************************************************************************
+ *
+ * Dummy PHY/MAC/Board operations
+ *
+ * Can be used where the MAC does not implement this operation
+ * Needed so all function pointers are valid and do not have to be tested
+ * before use
+ *
+ **************************************************************************/
+int efx_port_dummy_op_int(struct efx_nic *efx)
+{
+       return 0;
+}
+void efx_port_dummy_op_void(struct efx_nic *efx) {}
+void efx_port_dummy_op_blink(struct efx_nic *efx, int blink) {}
+
+static struct efx_mac_operations efx_dummy_mac_operations = {
+       .init           = efx_port_dummy_op_int,
+       .reconfigure    = efx_port_dummy_op_void,
+       .fini           = efx_port_dummy_op_void,
+};
+
+static struct efx_phy_operations efx_dummy_phy_operations = {
+       .init            = efx_port_dummy_op_int,
+       .reconfigure     = efx_port_dummy_op_void,
+       .check_hw        = efx_port_dummy_op_int,
+       .fini            = efx_port_dummy_op_void,
+       .clear_interrupt = efx_port_dummy_op_void,
+       .reset_xaui      = efx_port_dummy_op_void,
+};
+
+/* Dummy board operations */
+static int efx_nic_dummy_op_int(struct efx_nic *nic)
+{
+       return 0;
+}
+
+static void efx_nic_dummy_op_void(struct efx_nic *nic) {}
+
+static struct efx_board efx_dummy_board_info = {
+       .init    = efx_nic_dummy_op_int,
+       .init_leds = efx_port_dummy_op_int,
+       .set_fault_led = efx_port_dummy_op_blink,
+       .monitor = efx_nic_dummy_op_int,
+       .blink = efx_port_dummy_op_blink,
+       .fini    = efx_nic_dummy_op_void,
+};
+
+/**************************************************************************
+ *
+ * Data housekeeping
+ *
+ **************************************************************************/
+
+/* This zeroes out and then fills in the invariants in a struct
+ * efx_nic (including all sub-structures).
+ */
+static int efx_init_struct(struct efx_nic *efx, enum efx_type_index type,
+                          struct pci_dev *pci_dev)
+{
+       struct efx_channel *channel;
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+       int i, rc;
+
+       /* Initialise common structures */
+       memset(efx, 0, sizeof(*efx));
+       spin_lock_init(&efx->biu_lock);
+       spin_lock_init(&efx->phy_lock);
+       mutex_init(&efx->spi_lock);
+       sema_init(&efx->suspend_lock, 1);
+       INIT_WORK(&efx->reset_work, efx_reset_work);
+       INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
+       efx->pci_dev = pci_dev;
+       efx->state = STATE_INIT;
+       efx->reset_pending = RESET_TYPE_NONE;
+       strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
+       efx->board_info = efx_dummy_board_info;
+
+       efx->rx_checksum_enabled = 1;
+       spin_lock_init(&efx->netif_stop_lock);
+       spin_lock_init(&efx->stats_lock);
+       mutex_init(&efx->mac_lock);
+       efx->mac_op = &efx_dummy_mac_operations;
+       efx->phy_op = &efx_dummy_phy_operations;
+       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);
+
+       for (i = 0; i < EFX_MAX_CHANNELS; i++) {
+               channel = &efx->channel[i];
+               channel->efx = efx;
+               channel->channel = i;
+               channel->evqnum = i;
+               channel->work_pending = 0;
+       }
+       for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
+               tx_queue = &efx->tx_queue[i];
+               tx_queue->efx = efx;
+               tx_queue->queue = i;
+               tx_queue->buffer = NULL;
+               tx_queue->channel = &efx->channel[0]; /* for safety */
+       }
+       for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
+               rx_queue = &efx->rx_queue[i];
+               rx_queue->efx = efx;
+               rx_queue->queue = i;
+               rx_queue->channel = &efx->channel[0]; /* for safety */
+               rx_queue->buffer = NULL;
+               spin_lock_init(&rx_queue->add_lock);
+               INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
+       }
+
+       efx->type = efx_nic_types[type];
+
+       /* Sanity-check NIC type */
+       EFX_BUG_ON_PARANOID(efx->type->txd_ring_mask &
+                           (efx->type->txd_ring_mask + 1));
+       EFX_BUG_ON_PARANOID(efx->type->rxd_ring_mask &
+                           (efx->type->rxd_ring_mask + 1));
+       EFX_BUG_ON_PARANOID(efx->type->evq_size &
+                           (efx->type->evq_size - 1));
+       /* As close as we can get to guaranteeing that we don't overflow */
+       EFX_BUG_ON_PARANOID(efx->type->evq_size <
+                           (efx->type->txd_ring_mask + 1 +
+                            efx->type->rxd_ring_mask + 1));
+
+       EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
+
+       /* Higher numbered interrupt modes are less capable! */
+       efx->interrupt_mode = max(efx->type->max_interrupt_mode,
+                                 interrupt_mode);
+#if defined(EFX_NEED_DUMMY_MSIX)
+       if (efx->interrupt_mode == EFX_INT_MODE_MSIX)
+               efx->interrupt_mode = EFX_INT_MODE_MSI;
+#endif
+
+       /* Tasks that can fail are last */
+       efx->refill_workqueue = create_workqueue("sfc_refill");
+       if (!efx->refill_workqueue) {
+               rc = -ENOMEM;
+               goto fail1;
+       }
+
+       efx->workqueue = create_singlethread_workqueue("sfc_work");
+       if (!efx->workqueue) {
+               rc = -ENOMEM;
+               goto fail2;
+       }
+
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+       efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
+       if (!efx->reset_workqueue) {
+               rc = -ENOMEM;
+               goto fail3;
+       }
+#endif
+
+       return 0;
+
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+ fail3:
+       destroy_workqueue(efx->workqueue);
+       efx->workqueue = NULL;
+#endif
+
+ fail2:
+       destroy_workqueue(efx->refill_workqueue);
+       efx->refill_workqueue = NULL;
+ fail1:
+       return rc;
+}
+
+static void efx_fini_struct(struct efx_nic *efx)
+{
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+       if (efx->reset_workqueue) {
+               destroy_workqueue(efx->reset_workqueue);
+               efx->reset_workqueue = NULL;
+       }
+#endif
+       if (efx->workqueue) {
+               destroy_workqueue(efx->workqueue);
+               efx->workqueue = NULL;
+       }
+       if (efx->refill_workqueue) {
+               destroy_workqueue(efx->refill_workqueue);
+               efx->refill_workqueue = NULL;
+       }
+}
+
+/**************************************************************************
+ *
+ * PCI interface
+ *
+ **************************************************************************/
+
+/* Main body of final NIC shutdown code
+ * This is called only at module unload (or hotplug removal).
+ */
+static void efx_pci_remove_main(struct efx_nic *efx)
+{
+       ASSERT_RTNL();
+
+       /* Skip everything if we never obtained a valid membase */
+       if (!efx->membase)
+               return;
+
+       efx_fini_channels(efx);
+       efx_fini_port(efx);
+
+       /* Shutdown the board, then the NIC and board state */
+       efx->board_info.fini(efx);
+       falcon_fini_nic(efx);
+       falcon_fini_interrupt(efx);
+       efx->board_info.fini(efx);
+
+       /* Tear down NAPI and LRO */
+       efx_fini_napi(efx);
+       efx_remove_all(efx);
+}
+
+/* Final NIC shutdown
+ * This is called only at module unload (or hotplug removal).
+ */
+static void efx_pci_remove(struct pci_dev *pci_dev)
+{
+       struct efx_nic *efx;
+
+       efx = pci_get_drvdata(pci_dev);
+       if (!efx)
+               return;
+
+       /* Unregister driver from driverlink layer */
+       efx_dl_unregister_nic(efx);
+
+       /* Mark the NIC as fini under both suspend_lock and
+        * rtnl_lock */
+       down(&efx->suspend_lock);
+       rtnl_lock();
+       efx->state = STATE_FINI;
+       up(&efx->suspend_lock);
+
+       if (efx->membase) {
+               /* Stop the NIC. Since we're in STATE_FINI, this
+                * won't be reversed. */
+               if (efx->net_dev_registered)
+                       dev_close(efx->net_dev);
+
+               /* Release the rtnl lock. Any queued efx_resets()
+                * can now return early [we're in STATE_FINI]. */
+               rtnl_unlock();
+
+               efx_unregister_netdev(efx);
+               efx_fini_debugfs_channels(efx);
+
+               /* Wait for any scheduled resets to complete. No more will be
+                * scheduled from this point because efx_stop_all() has been
+                * called, we are no longer registered with driverlink, and
+                * the net_device's have been removed. */
+#if !defined(EFX_USE_CANCEL_DELAYED_WORK_SYNC)
+               flush_workqueue(efx->reset_workqueue);
+#else
+               flush_workqueue(efx->workqueue);
+#endif
+
+               /* Fini and remove all the software state */
+               rtnl_lock();
+               efx_pci_remove_main(efx);
+       }
+
+       rtnl_unlock();
+
+       efx_fini_io(efx);
+       EFX_LOG(efx, "shutdown successful\n");
+
+       pci_set_drvdata(pci_dev, NULL);
+       efx_fini_struct(efx);
+       kfree(efx);
+};
+
+/* Main body of NIC initialisation
+ * This is called at module load (or hotplug insertion, theoretically).
+ */
+static int efx_pci_probe_main(struct efx_nic *efx)
+{
+       int rc;
+
+       /* Do start-of-day initialisation */
+       rc = efx_probe_all(efx);
+       if (rc)
+               goto fail1;
+
+       /* Initialise port/channel net_dev's  */
+       rc = efx_init_napi(efx);
+       if (rc)
+               goto fail2;
+
+       /* Initialise the board */
+       rc = efx->board_info.init(efx);
+       if (rc) {
+               EFX_ERR(efx, "failed to initialise board\n");
+               goto fail3;
+       }
+
+       /* Initialise device */
+       rc = falcon_init_nic(efx);
+       if (rc) {
+               EFX_ERR(efx, "failed to initialise NIC\n");
+               goto fail4;
+       }
+
+       /* Initialise port */
+       rc = efx_init_port(efx);
+       if (rc) {
+               EFX_ERR(efx, "failed to initialise port\n");
+               goto fail5;
+       }
+
+       /* Initialise channels */
+       rc = efx_init_channels(efx);
+       if (rc)
+               goto fail6;
+
+       rc = falcon_init_interrupt(efx);
+       if (rc)
+               goto fail7;
+
+       /* Start up device - interrupts can occur from this point */
+       efx_start_all(efx);
+
+       /* Check basic functionality and set interrupt mode */
+       rc = efx_run_selftests(efx);
+       if (rc)
+               goto fail8;
+
+       /* Stop the NIC */
+       efx_stop_all(efx);
+
+       return 0;
+
+ fail8:
+       efx_stop_all(efx);
+       falcon_fini_interrupt(efx);
+ fail7:
+       efx_fini_channels(efx);
+ fail6:
+       efx_fini_port(efx);
+ fail5:
+       falcon_fini_nic(efx);
+ fail4:
+       efx->board_info.fini(efx);
+ fail3:
+       efx_fini_napi(efx);
+ fail2:
+       efx_remove_all(efx);
+ fail1:
+       return rc;
+}
+
+/* NIC initialisation
+ *
+ * This is called at module load (or hotplug insertion,
+ * theoretically).  It sets up PCI mappings, tests and resets the NIC,
+ * sets up and registers the network devices with the kernel and hooks
+ * the interrupt service routine.  It does not prepare the device for
+ * transmission; this is left to the first time one of the network
+ * interfaces is brought up (i.e. efx_net_open).
+ */
+static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
+                                  const struct pci_device_id *entry)
+{
+       struct efx_nic *efx;
+       enum efx_type_index type = entry->driver_data;
+       int i, rc;
+
+       /* Allocate and initialise a struct efx_nic */
+       efx = kmalloc(sizeof(*efx), GFP_KERNEL);
+       if (!efx) {
+               rc = -ENOMEM;
+               goto fail1;
+       }
+       pci_set_drvdata(pci_dev, efx);
+       rc = efx_init_struct(efx, type, pci_dev);
+       if (rc)
+               goto fail2;
+
+       EFX_INFO(efx, "Solarflare Communications NIC detected\n");
+
+       /* Set up basic I/O (BAR mappings etc) */
+       rc = efx_init_io(efx);
+       if (rc)
+               goto fail3;
+
+       /* From this point on we begin to expose the driver to the OS
+        * to varying degrees, so lets grab the suspend_lock and
+        * rtnl_lock to serialise against efx_reset() and
+        * friends. efx->state is not STATE_RUNNING yet, but we don't
+        * want these tasks to fail, just to block until we drop the
+        * lock
+        */
+       rc = down_interruptible(&efx->suspend_lock);
+       if (rc) {
+               EFX_ERR(efx, "suspend interrupted - aborting\n");
+               goto fail4;
+       }
+
+       rtnl_lock();
+
+       /* Probe, initialise and start everything. Run self-test */
+       for (i = 0; i < 5; i++) {
+               rc = efx_pci_probe_main(efx);
+               if (rc == 0)
+                       break;
+
+               /* Retry if a recoverably reset event has been scheduled */
+               if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
+                   (efx->reset_pending != RESET_TYPE_ALL))
+                       goto fail5;
+
+               /* Serialise against efx_reset(). No more resets will be
+                * scheduled since efx_stop_all() has been called, and we
+                * have not and never have been registered with either
+                * the rtnetlink or driverlink layers. */
+               rtnl_unlock();
+               up(&efx->suspend_lock);
+
+#if defined(EFX_USE_CANCEL_WORK_SYNC)
+               cancel_work_sync(&efx->reset_work);
+#else
+               flush_workqueue(efx->reset_workqueue);
+#endif
+
+               down(&efx->suspend_lock);
+               rtnl_lock();
+
+               efx->reset_pending = RESET_TYPE_NONE;
+       };
+       if (rc) {
+               EFX_ERR(efx, "Could not reset NIC\n");
+               goto fail5;
+       }
+
+       /* Self-tests have all passed */
+       rc = efx_init_debugfs_channels(efx);
+       if (rc)
+               goto fail6;
+
+       /* Switch to the running state before we expose the device to
+        * the OS.  This is to ensure that the initial gathering of
+        * MAC stats succeeds. */
+       efx->state = STATE_RUNNING;
+
+       rtnl_unlock();
+
+       rc = efx_register_netdev(efx);
+       if (rc)
+               goto fail7;
+
+       up(&efx->suspend_lock);
+
+       EFX_LOG(efx, "initialisation successful\n");
+
+       /* Register with driverlink layer */
+       rc = efx_dl_register_nic(efx);
+       if (rc)
+               goto fail8;
+
+       return 0;
+
+ fail8:
+       down(&efx->suspend_lock);
+       efx_unregister_netdev(efx);
+ fail7:
+       /* Re-acquire the rtnl lock around pci_remove_main() */
+       rtnl_lock();
+       efx_fini_debugfs_channels(efx);
+ fail6:
+       efx_pci_remove_main(efx);
+ fail5:
+       /* Drop the locks before fini */
+       rtnl_unlock();
+       up(&efx->suspend_lock);
+ fail4:
+       efx_fini_io(efx);
+ fail3:
+       efx_fini_struct(efx);
+ fail2:
+       kfree(efx);
+ fail1:
+       EFX_LOG(efx, "initialisation failed. rc=%d\n", rc);
+       return rc;
+}
+
+/* PCI driver definition */
+static struct pci_driver efx_pci_driver = {
+       .name           = EFX_DRIVER_NAME,
+       .id_table       = efx_pci_table,
+       .probe          = efx_pci_probe,
+       .remove         = efx_pci_remove,
+};
+
+/**************************************************************************
+ *
+ * Kernel module interface
+ *
+ *************************************************************************/
+
+module_param(interrupt_mode, uint, 0444);
+MODULE_PARM_DESC(interrupt_mode,
+                "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)");
+
+module_param(onload_offline_selftest, uint, 0444);
+MODULE_PARM_DESC(onload_offline_selftest, "Perform offline selftest on load");
+
+static int __init efx_init_module(void)
+{
+       int rc;
+
+       printk(KERN_INFO "Solarflare NET driver v" EFX_DRIVER_VERSION "\n");
+
+       rc = efx_init_debugfs();
+       if (rc)
+               goto err_debugfs;
+
+       rc = register_netdevice_notifier(&efx_netdev_notifier);
+       if (rc)
+               goto err_notifier;
+
+       rc = pci_register_driver(&efx_pci_driver);
+       if (rc < 0)
+               goto err_pci;
+
+       return 0;
+
+ err_pci:
+       unregister_netdevice_notifier(&efx_netdev_notifier);
+ err_notifier:
+       efx_fini_debugfs();
+ err_debugfs:
+       return rc;
+}
+
+static void __exit efx_exit_module(void)
+{
+       printk(KERN_INFO "Solarflare NET driver unloading\n");
+
+       pci_unregister_driver(&efx_pci_driver);
+       unregister_netdevice_notifier(&efx_netdev_notifier);
+       efx_fini_debugfs();
+
+}
+
+module_init(efx_init_module);
+module_exit(efx_exit_module);
+
+MODULE_AUTHOR("Michael Brown <mbrown@xxxxxxxxxxxxxxxx> and "
+             "Solarflare Communications");
+MODULE_DESCRIPTION("Solarflare Communications network driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, efx_pci_table);
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/efx.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/efx.h     Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2006-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_EFX_H
+#define EFX_EFX_H
+
+#include "net_driver.h"
+
+/* PCI IDs */
+#define EFX_VENDID_SFC         0x1924
+#define FALCON_A_P_DEVID       0x0703
+#define FALCON_A_S_DEVID        0x6703
+#define FALCON_B_P_DEVID        0x0710
+
+/* TX */
+extern int efx_xmit(struct efx_nic *efx,
+                   struct efx_tx_queue *tx_queue, struct sk_buff *skb);
+extern void efx_stop_queue(struct efx_nic *efx);
+extern void efx_wake_queue(struct efx_nic *efx);
+
+/* RX */
+#if defined(EFX_USE_FASTCALL)
+extern void fastcall efx_xmit_done(struct efx_tx_queue *tx_queue,
+                                  unsigned int index);
+#else
+extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+#endif
+#if defined(EFX_USE_FASTCALL)
+extern void fastcall efx_rx_packet(struct efx_rx_queue *rx_queue,
+                                  unsigned int index, unsigned int len,
+                                  int checksummed, int discard);
+#else
+extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
+                         unsigned int len, int checksummed, int discard);
+#endif
+extern void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
+                              struct efx_rx_buffer *rx_buf);
+
+/* Channels */
+extern void efx_process_channel_now(struct efx_channel *channel);
+extern int efx_flush_queues(struct efx_nic *efx);
+
+/* Ports */
+extern void efx_reconfigure_port(struct efx_nic *efx,
+                                int on_disabled);
+
+/* Global */
+extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
+extern void efx_suspend(struct efx_nic *efx);
+extern void efx_resume(struct efx_nic *efx);
+extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
+                                   int rx_usecs);
+extern int efx_request_power(struct efx_nic *efx, int mw, const char *name);
+extern void efx_hex_dump(const u8 *, unsigned int, const char *);
+
+/* Dummy PHY ops for PHY drivers */
+extern int efx_port_dummy_op_int(struct efx_nic *efx);
+extern void efx_port_dummy_op_void(struct efx_nic *efx);
+extern void efx_port_dummy_op_blink(struct efx_nic *efx, int blink);
+
+
+extern unsigned int efx_monitor_interval;
+
+static inline void efx_schedule_channel(struct efx_channel *channel)
+{
+       EFX_TRACE(channel->efx, "channel %d scheduling NAPI poll on CPU%d\n",
+                 channel->channel, raw_smp_processor_id());
+       channel->work_pending = 1;
+
+#if defined(EFX_HAVE_OLD_NAPI)
+       if (!test_and_set_bit(__LINK_STATE_RX_SCHED, &channel->napi_dev->state))
+               __netif_rx_schedule(channel->napi_dev);
+#else
+       netif_rx_schedule(channel->napi_dev, &channel->napi_str);
+#endif
+}
+
+
+#endif /* EFX_EFX_H */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/enum.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/enum.h    Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2007:      Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Developed by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_ENUM_H
+#define EFX_ENUM_H
+
+/**
+ * enum efx_loopback_mode - loopback modes
+ * @LOOPBACK_NONE: no loopback
+ * @LOOPBACK_NEAR: loopback nearest to bus
+ * @LOOPBACK_MAC: loopback within MAC unspecified level
+ * @LOOPBACK_XGMII: loopback within MAC at XGMII level
+ * @LOOPBACK_XGXS: loopback within MAC at XGXS level
+ * @LOOPBACK_XAUI: loopback within MAC at XAUI level
+ * @LOOPBACK_PHY: loopback within PHY unspecified level
+ * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level
+ * @LOOPBACK_PCS: loopback within PHY at PCS level
+ * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level
+ * @LOOPBACK_FAR: loopback furthest from bus
+ * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!)
+ */
+/* Please keep in order and up-to-date w.r.t the following two #defines */
+enum efx_loopback_mode {
+       LOOPBACK_NONE = 0,
+       LOOPBACK_NEAR = 1,
+       LOOPBACK_MAC = 2,
+       LOOPBACK_XGMII = 3,
+       LOOPBACK_XGXS = 4,
+       LOOPBACK_XAUI = 5,
+       LOOPBACK_PHY = 6,
+       LOOPBACK_PHYXS = 7,
+       LOOPBACK_PCS = 8,
+       LOOPBACK_PMAPMD = 9,
+       LOOPBACK_FAR = 10,
+       LOOPBACK_NETWORK = 11,
+       LOOPBACK_MAX
+};
+#define LOOPBACK_TEST_MAX LOOPBACK_FAR
+
+/* These loopbacks occur within the controller */
+#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \
+                               (1 << LOOPBACK_XGXS) | \
+                               (1 << LOOPBACK_XAUI))
+
+#define LOOPBACKS_1G_INTERNAL (1 << LOOPBACK_MAC)
+
+#define LOOPBACK_MASK(_efx)                    \
+       (1 << (_efx)->loopback_mode)
+
+#define LOOPBACK_INTERNAL(_efx)                                        \
+       (((LOOPBACKS_10G_INTERNAL | LOOPBACKS_1G_INTERNAL) &    \
+         LOOPBACK_MASK(_efx)) ? 1 : 0)
+
+#define LOOPBACK_CHANGED(_from, _to, _mask)            \
+       ((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) &  \
+        (_mask) ? 1 : 0)
+
+#define LOOPBACK_OUT_OF(_from, _to, _mask)             \
+       (((LOOPBACK_MASK(_from) & (_mask)) &&           \
+         ((LOOPBACK_MASK(_to) & (_mask)) == 0)) ? 1 : 0)
+
+/*****************************************************************************/
+
+/**
+ * enum reset_type - reset types
+ *
+ * %RESET_TYPE_INVSIBLE, %RESET_TYPE_ALL, %RESET_TYPE_WORLD and
+ * %RESET_TYPE_DISABLE specify the method/scope of the reset.  The
+ * other valuesspecify reasons, which efx_schedule_reset() will choose
+ * a method for.
+ *
+ * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts
+ * @RESET_TYPE_ALL: reset everything but PCI core blocks
+ * @RESET_TYPE_WORLD: reset everything, save & restore PCI config
+ * @RESET_TYPE_DISABLE: disable NIC
+ * @RESET_TYPE_MONITOR: reset due to hardware monitor
+ * @RESET_TYPE_INT_ERROR: reset due to internal error
+ * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
+ */
+enum reset_type {
+       RESET_TYPE_NONE = -1,
+       RESET_TYPE_INVISIBLE = 0,
+       RESET_TYPE_ALL = 1,
+       RESET_TYPE_WORLD = 2,
+       RESET_TYPE_DISABLE = 3,
+       RESET_TYPE_MAX_METHOD,
+       RESET_TYPE_MONITOR,
+       RESET_TYPE_INT_ERROR,
+       RESET_TYPE_RX_RECOVERY,
+       RESET_TYPE_RX_DESC_FETCH,
+       RESET_TYPE_TX_DESC_FETCH,
+       RESET_TYPE_MAX,
+};
+
+#endif /* EFX_ENUM_H */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/ethtool.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/ethtool.c Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,734 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2006-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include <asm/uaccess.h>
+#include "net_driver.h"
+#include "selftest.h"
+#include "efx.h"
+#include "ethtool.h"
+#include "falcon.h"
+#include "gmii.h"
+
+static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable);
+
+struct ethtool_string {
+       char name[ETH_GSTRING_LEN];
+};
+
+struct efx_ethtool_stat {
+       const char *name;
+       enum {
+               EFX_ETHTOOL_STAT_SOURCE_mac_stats,
+               EFX_ETHTOOL_STAT_SOURCE_nic,
+               EFX_ETHTOOL_STAT_SOURCE_channel
+       } source;
+       unsigned offset;
+       u64(*get_stat) (void *field); /* Reader function */
+};
+
+/* Initialiser for a struct #efx_ethtool_stat with type-checking */
+#define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \
+                               get_stat_function) {                    \
+       .name = #stat_name,                                             \
+       .source = EFX_ETHTOOL_STAT_SOURCE_##source_name,                \
+       .offset = ((((field_type *) 0) ==                               \
+                     &((struct efx_##source_name *)0)->field) ?        \
+                   offsetof(struct efx_##source_name, field) :         \
+                   offsetof(struct efx_##source_name, field)),         \
+       .get_stat = get_stat_function,                                  \
+}
+
+static u64 efx_get_uint_stat(void *field)
+{
+       return *(unsigned int *)field;
+}
+
+static u64 efx_get_ulong_stat(void *field)
+{
+       return *(unsigned long *)field;
+}
+
+static u64 efx_get_u64_stat(void *field)
+{
+       return *(u64 *) field;
+}
+
+static u64 efx_get_atomic_stat(void *field)
+{
+       return atomic_read((atomic_t *) field);
+}
+
+#define EFX_ETHTOOL_ULONG_MAC_STAT(field)                      \
+       EFX_ETHTOOL_STAT(field, mac_stats, field,               \
+                         unsigned long, efx_get_ulong_stat)
+
+#define EFX_ETHTOOL_U64_MAC_STAT(field)                                \
+       EFX_ETHTOOL_STAT(field, mac_stats, field,               \
+                         u64, efx_get_u64_stat)
+
+#define EFX_ETHTOOL_UINT_NIC_STAT(name)                                \
+       EFX_ETHTOOL_STAT(name, nic, n_##name,                   \
+                        unsigned int, efx_get_uint_stat)
+
+#define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field)               \
+       EFX_ETHTOOL_STAT(field, nic, errors.field,              \
+                        atomic_t, efx_get_atomic_stat)
+
+#define EFX_ETHTOOL_UINT_CHANNEL_STAT(field)                   \
+       EFX_ETHTOOL_STAT(field, channel, n_##field,             \
+                        unsigned int, efx_get_uint_stat)
+
+static struct efx_ethtool_stat efx_ethtool_stats[] = {
+       EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
+       EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
+       EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_control),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_64),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error),
+       EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error),
+       EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
+       EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
+       EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_good),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_control),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_64),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error),
+       EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error),
+       EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt),
+       EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
+       EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
+       EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
+       EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
+       EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
+};
+
+/* Number of ethtool statistics */
+#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
+
+/**************************************************************************
+ *
+ * Ethtool operations
+ *
+ **************************************************************************
+ */
+
+/* Identify device by flashing LEDs */
+static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       efx->board_info.blink(efx, 1);
+       schedule_timeout_interruptible(seconds * HZ);
+       efx->board_info.blink(efx, 0);
+       return 0;
+}
+
+/* This must be called with rtnl_lock held. */
+int efx_ethtool_get_settings(struct net_device *net_dev,
+                            struct ethtool_cmd *ecmd)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       return efx->mac_op->get_settings(efx, ecmd);
+}
+
+/* This must be called with rtnl_lock held. */
+int efx_ethtool_set_settings(struct net_device *net_dev,
+                            struct ethtool_cmd *ecmd)
+{
+       struct efx_nic *efx = net_dev->priv;
+       int rc;
+
+       rc = efx->mac_op->set_settings(efx, ecmd);
+       if (rc)
+               return rc;
+
+       /* Push the settings to the MAC */
+       efx_reconfigure_port(efx, 0);
+
+       return 0;
+}
+
+static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
+                                   struct ethtool_drvinfo *info)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver));
+       strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
+       strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
+}
+
+/**
+ * efx_fill_test - fill in an individual self-test entry
+ * @test_index:                Index of the test
+ * @strings:           Ethtool strings, or %NULL
+ * @data:              Ethtool test results, or %NULL
+ * @test:              Pointer to test result (used only if data != %NULL)
+ * @unit_format:       Unit name format (e.g. "channel\%d")
+ * @unit_id:           Unit id (e.g. 0 for "channel0")
+ * @test_format:       Test name format (e.g. "loopback.\%s.tx.sent")
+ * @test_id:           Test id (e.g. "PHY" for "loopback.PHY.tx_sent")
+ *
+ * Fill in an individual self-test entry.
+ */
+static void efx_fill_test(unsigned int test_index,
+                         struct ethtool_string *strings, u64 *data,
+                         int *test, const char *unit_format, int unit_id,
+                         const char *test_format, const char *test_id)
+{
+       struct ethtool_string unit_str, test_str;
+
+       /* Fill data value, if applicable */
+       if (data)
+               data[test_index] = *test;
+
+       /* Fill string, if applicable */
+       if (strings) {
+               snprintf(unit_str.name, sizeof(unit_str.name),
+                        unit_format, unit_id);
+               snprintf(test_str.name, sizeof(test_str.name),
+                        test_format, test_id);
+               snprintf(strings[test_index].name,
+                        sizeof(strings[test_index].name),
+                        "%-9s%-17s", unit_str.name, test_str.name);
+       }
+}
+
+#define EFX_PORT_NAME "port%d", 0
+
+/**
+ * efx_fill_loopback_test - fill in a block of loopback self-test entries
+ * @efx:               Efx NIC
+ * @lb_tests:          Efx loopback self-test results structure
+ * @mode:              Loopback test mode
+ * @test_index:                Starting index of the test
+ * @strings:           Ethtool strings, or %NULL
+ * @data:              Ethtool test results, or %NULL
+ *
+ * Fill in a block of loopback self-test entries.  Return new test
+ * index.
+ */
+static int efx_fill_loopback_test(struct efx_nic *efx,
+                                 struct efx_loopback_self_tests *lb_tests,
+                                 enum efx_loopback_mode mode,
+                                 unsigned int test_index,
+                                 struct ethtool_string *strings, u64 *data)
+{
+       struct efx_tx_queue *tx_queue;
+
+       efx_for_each_tx_queue(tx_queue, efx) {
+               efx_fill_test(test_index++, strings, data,
+                             &lb_tests->tx_sent[tx_queue->queue],
+                             EFX_TX_QUEUE_NAME(tx_queue),
+                             "loopback.%s.tx_sent",
+                             efx_loopback_mode_names[mode]);
+               efx_fill_test(test_index++, strings, data,
+                             &lb_tests->tx_done[tx_queue->queue],
+                             EFX_TX_QUEUE_NAME(tx_queue),
+                             "loopback.%s.tx_done",
+                             efx_loopback_mode_names[mode]);
+       }
+       efx_fill_test(test_index++, strings, data,
+                     &lb_tests->rx_good,
+                     EFX_PORT_NAME,
+                     "loopback.%s.rx_good",
+                     efx_loopback_mode_names[mode]);
+       efx_fill_test(test_index++, strings, data,
+                     &lb_tests->rx_bad,
+                     EFX_PORT_NAME,
+                     "loopback.%s.rx_bad",
+                     efx_loopback_mode_names[mode]);
+
+       return test_index;
+}
+
+/**
+ * efx_ethtool_fill_self_tests - get self-test details
+ * @efx:               Efx NIC
+ * @tests:             Efx self-test results structure, or %NULL
+ * @strings:           Ethtool strings, or %NULL
+ * @data:              Ethtool test results, or %NULL
+ *
+ * Get self-test number of strings, strings, and/or test results.
+ * Return number of strings (== number of test results).
+ *
+ * The reason for merging these three functions is to make sure that
+ * they can never be inconsistent.
+ */
+static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
+                                      struct efx_self_tests *tests,
+                                      struct ethtool_string *strings,
+                                      u64 *data)
+{
+       struct efx_channel *channel;
+       unsigned int n = 0;
+       enum efx_loopback_mode mode;
+
+       /* Interrupt */
+       efx_fill_test(n++, strings, data, &tests->interrupt,
+                     "core", 0, "interrupt", NULL);
+
+       /* Event queues */
+       efx_for_each_channel(channel, efx) {
+               efx_fill_test(n++, strings, data,
+                             &tests->eventq_dma[channel->channel],
+                             EFX_CHANNEL_NAME(channel),
+                             "eventq.dma", NULL);
+               efx_fill_test(n++, strings, data,
+                             &tests->eventq_int[channel->channel],
+                             EFX_CHANNEL_NAME(channel),
+                             "eventq.int", NULL);
+               efx_fill_test(n++, strings, data,
+                             &tests->eventq_poll[channel->channel],
+                             EFX_CHANNEL_NAME(channel),
+                             "eventq.poll", NULL);
+       }
+
+       /* PHY presence */
+       efx_fill_test(n++, strings, data, &tests->phy_ok,
+                     EFX_PORT_NAME, "phy_ok", NULL);
+
+       /* Loopback tests */
+       efx_fill_test(n++, strings, data, &tests->loopback_speed,
+                     EFX_PORT_NAME, "loopback.speed", NULL);
+       efx_fill_test(n++, strings, data, &tests->loopback_full_duplex,
+                     EFX_PORT_NAME, "loopback.full_duplex", NULL);
+       for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) {
+               if (!(efx->loopback_modes & (1 << mode)))
+                       continue;
+               n = efx_fill_loopback_test(efx,
+                                          &tests->loopback[mode], mode, n,
+                                          strings, data);
+       }
+
+       return n;
+}
+
+static int efx_ethtool_get_stats_count(struct net_device *net_dev)
+{
+       return EFX_ETHTOOL_NUM_STATS;
+}
+
+static int efx_ethtool_self_test_count(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
+}
+
+static void efx_ethtool_get_strings(struct net_device *net_dev,
+                                   u32 string_set, u8 *strings)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct ethtool_string *ethtool_strings =
+               (struct ethtool_string *)strings;
+       int i;
+
+       switch (string_set) {
+       case ETH_SS_STATS:
+               for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++)
+                       strncpy(ethtool_strings[i].name,
+                               efx_ethtool_stats[i].name,
+                               sizeof(ethtool_strings[i].name));
+               break;
+       case ETH_SS_TEST:
+               efx_ethtool_fill_self_tests(efx, NULL,
+                                           ethtool_strings, NULL);
+               break;
+       default:
+               /* No other string sets */
+               break;
+       }
+}
+
+static void efx_ethtool_get_stats(struct net_device *net_dev,
+                                 struct ethtool_stats *stats
+                                 __attribute__ ((unused)), u64 *data)
+{
+       unsigned long flags __attribute__ ((unused));
+       struct efx_nic *efx = net_dev->priv;
+       struct efx_mac_stats *mac_stats = &efx->mac_stats;
+       struct efx_ethtool_stat *stat;
+       struct efx_channel *channel;
+       int i;
+
+       EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);
+
+       /* Update MAC and NIC statistics */
+       net_dev->get_stats(net_dev);
+       falcon_update_nic_stats(efx);
+
+       /* Fill detailed statistics buffer */
+       for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
+               stat = &efx_ethtool_stats[i];
+               switch (stat->source) {
+               case EFX_ETHTOOL_STAT_SOURCE_mac_stats:
+                       data[i] = stat->get_stat((void *)mac_stats +
+                                                stat->offset);
+                       break;
+               case EFX_ETHTOOL_STAT_SOURCE_nic:
+                       data[i] = stat->get_stat((void *)efx + stat->offset);
+                       break;
+               case EFX_ETHTOOL_STAT_SOURCE_channel:
+                       data[i] = 0;
+                       efx_for_each_channel(channel, efx)
+                               data[i] += stat->get_stat((void *)channel +
+                                                         stat->offset);
+                       break;
+               }
+       }
+}
+
+static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
+{
+       struct efx_nic *efx = net_dev->priv;
+       int rc;
+
+       rc = ethtool_op_set_tx_csum(net_dev, enable);
+       if (rc)
+               return rc;
+
+
+       efx_flush_queues(efx);
+
+       return 0;
+}
+
+static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       /* No way to stop the hardware doing the checks; we just
+        * ignore the result.
+        */
+       efx->rx_checksum_enabled = (enable ? 1 : 0);
+
+       return 0;
+}
+
+static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       return efx->rx_checksum_enabled;
+}
+
+static void efx_ethtool_self_test(struct net_device *net_dev,
+                                 struct ethtool_test *test, u64 *data)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct efx_self_tests efx_tests;
+       int offline, already_up;
+       int rc;
+
+       /* Make sure we've got rtnl lock since we're playing with
+        * interrupts, and calling efx_process_channel_now and others
+        */
+       ASSERT_RTNL();
+
+       /* If the NIC isn't in the RUNNING state then exit */
+       if (efx->state != STATE_RUNNING) {
+               rc = -EIO;
+               goto fail1;
+       }
+
+       /* Make sure the interface is up. We need interrupts, NAPI
+        * and some RX buffers so this is helpful.  NB. The caller has
+        * rtnl_lock so nobody else can call dev_open. */
+       already_up = (efx->net_dev->flags & IFF_UP);
+       if (!already_up) {
+               rc = dev_open(efx->net_dev);
+               if (rc) {
+                       EFX_ERR(efx, "failed opening device.\n");
+                       goto fail2;
+               }
+       }
+
+       memset(&efx_tests, 0, sizeof(efx_tests));
+       offline = (test->flags & ETH_TEST_FL_OFFLINE);
+
+       /* Perform online self tests first */
+       rc = efx_online_test(efx, &efx_tests);
+       if (rc)
+               goto out;
+
+       /* Perform offline tests only if online tests passed */
+       if (offline) {
+               /* Stop the kernel from sending packets during the test. The
+                * selftest will be consistently bringing the port up and down
+                * as it moves between loopback modes, so the watchdog timer
+                * probably won't run anyway */
+               efx_stop_queue(efx);
+
+               rc = efx_flush_queues(efx);
+               if (rc != 0)
+                       goto out_offline;
+
+               rc = efx_offline_test(efx, &efx_tests,
+                                     efx->loopback_modes);
+ out_offline:
+               efx_wake_queue(efx);
+       }
+
+       /* fall-thru */
+ out:
+       if (!already_up)
+               dev_close(efx->net_dev);
+
+       EFX_LOG(efx, "%s all %sline self-tests\n",
+               rc == 0 ? "passed" : "failed", offline ? "off" : "on");
+
+ fail2:
+ fail1:
+       /* Fill ethtool results structures */
+       efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data);
+       if (rc)
+               test->flags |= ETH_TEST_FL_FAILED;
+}
+
+/* Restart autonegotiation */
+static int efx_ethtool_nway_reset(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       return mii_nway_restart(&efx->mii);
+}
+
+static u32 efx_ethtool_get_link(struct net_device *net_dev)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       return efx->link_up;
+}
+
+static int efx_ethtool_get_coalesce(struct net_device *net_dev,
+                                   struct ethtool_coalesce *coalesce)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct efx_tx_queue *tx_queue;
+       struct efx_rx_queue *rx_queue;
+       struct efx_channel *channel;
+
+       memset(coalesce, 0, sizeof(*coalesce));
+
+       /* Find lowest IRQ moderation across all used TX queues */
+       coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
+       efx_for_each_tx_queue(tx_queue, efx) {
+               channel = tx_queue->channel;
+               if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
+                       if (channel->used_flags != EFX_USED_BY_RX_TX)
+                               coalesce->tx_coalesce_usecs_irq =
+                                       channel->irq_moderation;
+                       else
+                               coalesce->tx_coalesce_usecs_irq = 0;
+               }
+       }
+
+       /* Find lowest IRQ moderation across all used RX queues */
+       coalesce->rx_coalesce_usecs_irq = ~((u32) 0);
+       efx_for_each_rx_queue(rx_queue, efx) {
+               channel = rx_queue->channel;
+               if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq)
+                       coalesce->rx_coalesce_usecs_irq =
+                               channel->irq_moderation;
+       }
+
+       return 0;
+}
+
+/* Set coalescing parameters
+ * The difficulties occur for shared channels
+ */
+static int efx_ethtool_set_coalesce(struct net_device *net_dev,
+                                   struct ethtool_coalesce *coalesce)
+{
+       struct efx_nic *efx = net_dev->priv;
+       struct efx_channel *channel;
+       struct efx_tx_queue *tx_queue;
+       unsigned tx_usecs, rx_usecs;
+
+       if (coalesce->use_adaptive_rx_coalesce ||
+           coalesce->use_adaptive_tx_coalesce)
+               return -EOPNOTSUPP;
+
+       if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) {
+               EFX_ERR(efx, "invalid coalescing setting. "
+                       "Only rx/tx_coalesce_usecs_irq are supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       rx_usecs = coalesce->rx_coalesce_usecs_irq;
+       tx_usecs = coalesce->tx_coalesce_usecs_irq;
+
+       /* If the channel is shared only allow RX parameters to be set */
+       efx_for_each_tx_queue(tx_queue, efx) {
+               if ((tx_queue->channel->used_flags == EFX_USED_BY_RX_TX) &&
+                   tx_usecs) {
+                       EFX_ERR(efx, "Channel is shared. "
+                               "Only RX coalescing may be set\n");
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       efx_init_irq_moderation(efx, tx_usecs, rx_usecs);
+
+       /* Reset channel to pick up new moderation value.  Note that
+        * this may change the value of the irq_moderation field
+        * (e.g. to allow for hardware timer granularity).
+        */
+       efx_for_each_channel(channel, efx)
+               falcon_set_int_moderation(channel);
+
+       return 0;
+}
+
+static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
+                                     struct ethtool_pauseparam *pause)
+{
+       struct efx_nic *efx = net_dev->priv;
+       enum efx_fc_type flow_control = efx->flow_control;
+       int rc;
+
+       flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO);
+       flow_control |= pause->rx_pause ? EFX_FC_RX : 0;
+       flow_control |= pause->tx_pause ? EFX_FC_TX : 0;
+       flow_control |= pause->autoneg ? EFX_FC_AUTO : 0;
+
+       /* Try to push the pause parameters */
+       rc = efx->mac_op->set_pause(efx, flow_control);
+       if (rc)
+               return rc;
+
+       /* Push the settings to the MAC */
+       efx_reconfigure_port(efx, 0);
+
+       return 0;
+}
+
+static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
+                                      struct ethtool_pauseparam *pause)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       pause->rx_pause = (efx->flow_control & EFX_FC_RX) ? 1 : 0;
+       pause->tx_pause = (efx->flow_control & EFX_FC_TX) ? 1 : 0;
+       pause->autoneg = (efx->flow_control & EFX_FC_AUTO) ? 1 : 0;
+}
+
+
+#if defined(EFX_USE_ETHTOOL_GET_PERM_ADDR)
+static int efx_ethtool_op_get_perm_addr(struct net_device *net_dev,
+                                       struct ethtool_perm_addr *addr,
+                                       u8 *data)
+{
+       struct efx_nic *efx = net_dev->priv;
+
+       memcpy(data, efx->mac_address, ETH_ALEN);
+
+       return 0;
+}
+#endif
+
+struct ethtool_ops efx_ethtool_ops = {
+       .get_settings           = efx_ethtool_get_settings,
+       .set_settings           = efx_ethtool_set_settings,
+       .get_drvinfo            = efx_ethtool_get_drvinfo,
+       .nway_reset             = efx_ethtool_nway_reset,
+       .get_link               = efx_ethtool_get_link,
+       .get_coalesce           = efx_ethtool_get_coalesce,
+       .set_coalesce           = efx_ethtool_set_coalesce,
+       .get_pauseparam         = efx_ethtool_get_pauseparam,
+       .set_pauseparam         = efx_ethtool_set_pauseparam,
+       .get_rx_csum            = efx_ethtool_get_rx_csum,
+       .set_rx_csum            = efx_ethtool_set_rx_csum,
+       .get_tx_csum            = ethtool_op_get_tx_csum,
+       .set_tx_csum            = efx_ethtool_set_tx_csum,
+       .get_sg                 = ethtool_op_get_sg,
+       .set_sg                 = ethtool_op_set_sg,
+#if defined(EFX_USE_ETHTOOL_FLAGS)
+       .get_flags              = ethtool_op_get_flags,
+       .set_flags              = ethtool_op_set_flags,
+#endif
+       .self_test_count        = efx_ethtool_self_test_count,
+       .self_test              = efx_ethtool_self_test,
+       .get_strings            = efx_ethtool_get_strings,
+       .phys_id                = efx_ethtool_phys_id,
+       .get_stats_count        = efx_ethtool_get_stats_count,
+       .get_ethtool_stats      = efx_ethtool_get_stats,
+#if defined(EFX_USE_ETHTOOL_GET_PERM_ADDR)
+       .get_perm_addr          = efx_ethtool_op_get_perm_addr,
+#endif
+};
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/ethtool.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/ethtool.h Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005:      Fen Systems Ltd.
+ * Copyright 2006:      Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 EFX_ETHTOOL_H
+#define EFX_ETHTOOL_H
+
+#include "net_driver.h"
+
+/*
+ * Ethtool support
+ */
+
+extern int efx_ethtool_get_settings(struct net_device *net_dev,
+                                   struct ethtool_cmd *ecmd);
+extern int efx_ethtool_set_settings(struct net_device *net_dev,
+                                   struct ethtool_cmd *ecmd);
+
+extern struct ethtool_ops efx_ethtool_ops;
+
+#endif /* EFX_ETHTOOL_H */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/extraversion.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/extraversion.h    Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,4 @@
+/*
+ * If compiling on kernels with backported features you may need to
+ * define EFX_DIST_KVER_ symbols here
+ */
diff -r 31d71546a644 -r 594bfb5cbe40 drivers/net/sfc/falcon.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/net/sfc/falcon.c  Tue Feb 19 11:15:05 2008 -0700
@@ -0,0 +1,3708 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * Copyright 2005-2006: Fen Systems Ltd.
+ * Copyright 2006-2008: Solarflare Communications Inc,
+ *                      9501 Jeronimo Road, Suite 250,
+ *                      Irvine, CA 92618, USA
+ *
+ * Initially developed by Michael Brown <mbrown@xxxxxxxxxxxxxxxx>
+ * Maintained by Solarflare Communications <linux-net-drivers@xxxxxxxxxxxxxx>
+ *
+ * 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 <asm/io.h>
+#include <asm/bitops.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include "net_driver.h"
+#include "bitfield.h"
+#include "efx.h"
+#include "mac.h"
+#include "gmii.h"
+#include "spi.h"
+#include "falcon.h"
+#include "falcon_hwdefs.h"
+#include "falcon_io.h"
+#include "mdio_10g.h"
+#include "phy.h"
+#include "boards.h"
+#include "driverlink.h"
+#include "workarounds.h"
+
+/* Falcon hardware control.
+ * Falcon is the internal codename for the SFC4000 controller that is
+ * present in SFE400X evaluation boards
+ */
+
+struct falcon_nic_data {
+       /* Number of entries in each TX queue descriptor cache. */
+       unsigned tx_dc_entries;
+       /* Number of entries in each RX queue descriptor cache. */
+       unsigned rx_dc_entries;
+       /* Base address in SRAM of TX queue descriptor caches. */
+       unsigned tx_dc_base;
+       /* Base address in SRAM of RX queue descriptor caches. */
+       unsigned rx_dc_base;
+
+       /* Previous loopback mode used in deconfigure_mac_wrapper */
+       enum efx_loopback_mode old_loopback_mode;
+
+       /* Driverlink parameters */
+       struct efx_dl_falcon_resources resources;
+};
+
+/**************************************************************************
+ *
+ * Configurable values
+ *
+ **************************************************************************
+ */
+
+static int disable_dma_stats;
+
+/* Specify the size of the RX descriptor cache */
+static int descriptor_cache_size = 64;
+
+/*
+ * Override EEPROM/flash type from non-volatile configuration or GPIO;
+ * may need to be specified if bootstrapping from blank flash.
+ */
+static unsigned int eeprom_type = -1;
+static unsigned int flash_type = -1;
+
+/* RX FIFO XOFF watermark
+ *
+ * When the amount of the RX FIFO increases used increases past this
+ * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A)
+ * This also has an effect on RX/TX arbitration
+ */
+static int rx_xoff_thresh_bytes = -1;
+module_param(rx_xoff_thresh_bytes, int, 0644);
+MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold");
+
+/* RX FIFO XON watermark
+ *
+ * When the amount of the RX FIFO used decreases below this
+ * watermark send XON. Only used if TX flow control is enabled (ethtool -A)
+ * This also has an effect on RX/TX arbitration
+ */
+static int rx_xon_thresh_bytes = -1;
+module_param(rx_xon_thresh_bytes, int, 0644);
+MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
+
+/* TX descriptor ring size - min 512 max 4k */
+#define FALCON_TXD_RING_ORDER TX_DESCQ_SIZE_1K
+#define FALCON_TXD_RING_SIZE 1024
+#define FALCON_TXD_RING_MASK (FALCON_TXD_RING_SIZE - 1)
+
+/* RX descriptor ring size - min 512 max 4k */
+#define FALCON_RXD_RING_ORDER RX_DESCQ_SIZE_1K
+#define FALCON_RXD_RING_SIZE 1024
+#define FALCON_RXD_RING_MASK (FALCON_RXD_RING_SIZE - 1)
+
+/* Event queue size - max 32k */
+#define FALCON_EVQ_ORDER EVQ_SIZE_4K
+#define FALCON_EVQ_SIZE 4096
+#define FALCON_EVQ_MASK (FALCON_EVQ_SIZE - 1)
+
+/* Max number of internal errors. After this resets will not be performed */
+#define FALCON_MAX_INT_ERRORS 4
+
+/* Maximum period that we wait for flush events. If the flush event
+ * doesn't arrive in this period of time then we check if the queue
+ * was disabled anyway. */
+#define FALCON_FLUSH_TIMEOUT 10 /* 10ms */
+
+/**************************************************************************
+ *
+ * Falcon constants
+ *
+ **************************************************************************
+ */
+
+/* DMA address mask (up to 46-bit, avoiding compiler warnings)
+ *
+ * Note that it is possible to have a platform with 64-bit longs and
+ * 32-bit DMA addresses, or vice versa.  EFX_DMA_MASK takes care of the
+ * platform DMA mask.
+ */
+#if BITS_PER_LONG == 64
+#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffUL)
+#else
+#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffULL)
+#endif
+
+/* TX DMA length mask (13-bit) */
+#define FALCON_TX_DMA_MASK (8192 - 1)
+
+/* Alignment of special buffers (4KB) */
+#define FALCON_BUF_ALIGN 4096
+
+/* Dummy SRAM size code */
+#define SRM_NB_BSZ_ONCHIP_ONLY (-1)
+
+/* Be nice if these (or equiv.) were in linux/pci_regs.h, but they're not. */
+#define PCI_EXP_DEVCAP_PWR_VAL_LBN     (18)
+/* This field takes up bits 26 and 27. */
+#define PCI_EXP_DEVCAP_PWR_SCL_LBN     (26)
+#define PCI_EXP_LNKSTA_LNK_WID         (0x3f0)
+#define PCI_EXP_LNKSTA_LNK_WID_LBN     (4)
+
+
+/**************************************************************************
+ *
+ * Falcon hardware access
+ *
+ **************************************************************************/
+
+/* Read the current event from the event queue */
+static inline efx_qword_t *falcon_event(struct efx_channel *channel,
+                                       unsigned int index)
+{
+       return (((efx_qword_t *) (channel->eventq.addr)) + index);
+}
+
+/* See if an event is present
+ *
+ * We check both the high and low dword of the event for all ones.  We
+ * wrote all ones when we cleared the event, and no valid event can
+ * have all ones in either its high or low dwords.  This approach is
+ * robust against reordering.
+ *
+ * Note that using a single 64-bit comparison is incorrect; even
+ * though the CPU read will be atomic, the DMA write may not be.
+ */
+static inline int falcon_event_present(efx_qword_t *event)
+{
+       return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
+                 EFX_DWORD_IS_ALL_ONES(event->dword[1])));
+}
+
+/* Read dword from a Falcon PCIE core register */
+static void falcon_pcie_core_read_reg(struct efx_nic *efx, int address,
+                                     efx_dword_t *result)
+{
+       efx_oword_t temp;
+
+       BUG_ON(FALCON_REV(efx) < FALCON_REV_B0);
+       BUG_ON(address & 3 || address < 0);
+
+       EFX_POPULATE_OWORD_1(temp, PCIE_CORE_ADDR, address);
+
+       falcon_write(efx, &temp, PCIE_CORE_INDIRECT_REG);
+       falcon_read(efx, &temp, PCIE_CORE_INDIRECT_REG);
+       /* Extract PCIE_CORE_VALUE without byte-swapping */
+       BUILD_BUG_ON(PCIE_CORE_VALUE_LBN != 32 ||
+                    PCIE_CORE_VALUE_WIDTH != 32);
+       result->u32[0] = temp.u32[1];
+}
+
+/* Write dword to a Falcon PCIE core register */
+static void falcon_pcie_core_write_reg(struct efx_nic *efx, int address,
+                                      efx_dword_t value)
+{
+       efx_oword_t temp;
+
+       BUG_ON(FALCON_REV(efx) < FALCON_REV_B0);
+       BUG_ON(address & 0x3 || address < 0);
+
+       EFX_POPULATE_OWORD_2(temp,
+                            PCIE_CORE_ADDR, address,
+                            PCIE_CORE_RW, 1);
+       /* Fill PCIE_CORE_VALUE without byte-swapping */
+       BUILD_BUG_ON(PCIE_CORE_VALUE_LBN != 32 ||
+                    PCIE_CORE_VALUE_WIDTH != 32);
+       temp.u32[1] = value.u32[0];
+       falcon_write(efx, &temp, PCIE_CORE_INDIRECT_REG);
+}
+
+/**************************************************************************
+ *
+ * I2C bus - this is a bit-bashing interface using GPIO pins
+ * Note that it uses the output enables to tristate the outputs
+ * SDA is the data pin and SCL is the clock
+ *
+ **************************************************************************
+ */
+static void falcon_setsdascl(struct efx_i2c_interface *i2c)
+{
+       efx_oword_t reg;
+
+       falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
+       EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, (i2c->scl ? 0 : 1));
+       EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, (i2c->sda ? 0 : 1));
+       falcon_write(i2c->efx, &reg, GPIO_CTL_REG_KER);
+}
+
+static int falcon_getsda(struct efx_i2c_interface *i2c)
+{
+       efx_oword_t reg;
+
+       falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
+       return EFX_OWORD_FIELD(reg, GPIO3_IN);
+}
+
+static int falcon_getscl(struct efx_i2c_interface *i2c)
+{
+       efx_oword_t reg;
+
+       falcon_read(i2c->efx, &reg, GPIO_CTL_REG_KER);
+       return EFX_DWORD_FIELD(reg, GPIO0_IN);
+}
+
+static struct efx_i2c_bit_operations falcon_i2c_bit_operations = {
+       .setsda         = falcon_setsdascl,
+       .setscl         = falcon_setsdascl,
+       .getsda         = falcon_getsda,
+       .getscl         = falcon_getscl,
+       .udelay         = 100,
+       .mdelay         = 10,
+};
+
+/**************************************************************************
+ *
+ * Falcon special buffer handling
+ * Special buffers are used for event queues and the TX and RX
+ * descriptor rings.
+ *
+ *************************************************************************/
+
+/* Adds the relevant entries to the full-mode buffer table. */
+static int
+falcon_pin_special_buffer_full(struct efx_nic *efx,
+                              struct efx_special_buffer *buffer)
+{
+       efx_qword_t buf_desc;
+       int index;
+       dma_addr_t dma_addr;
+       int i;
+
+       /* Write buffer descriptors to NIC */
+       for (i = 0; i < buffer->entries; i++) {
+               index = buffer->index + i;
+               dma_addr = buffer->dma_addr + (i * 4096);
+               EFX_LOG(efx, "mapping special buffer %d at %llx\n",
+                       index, (unsigned long long)dma_addr);
+               EFX_POPULATE_QWORD_4(buf_desc,
+                                    IP_DAT_BUF_SIZE, IP_DAT_BUF_SIZE_4K,
+                                    BUF_ADR_REGION, 0,
+                                    BUF_ADR_FBUF, (dma_addr >> 12),
+                                    BUF_OWNER_ID_FBUF, 0);
+               falcon_write_sram(efx, &buf_desc, index);
+       }
+
+       return 0;
+}
+
+/* Clears the relevant entries from the buffer table */
+static void
+falcon_clear_special_buffer_full(struct efx_nic *efx,
+                                struct efx_special_buffer *buffer)
+{
+       efx_oword_t buf_tbl_upd;
+       unsigned int start = buffer->index;
+       unsigned int end = (buffer->index + buffer->entries - 1);
+
+       EFX_LOG(efx, "unmapping special buffers %d-%d\n",
+               buffer->index, buffer->index + buffer->entries - 1);
+
+       EFX_POPULATE_OWORD_4(buf_tbl_upd,
+                            BUF_UPD_CMD, 0,
+                            BUF_CLR_CMD, 1,
+                            BUF_CLR_END_ID, end,
+                            BUF_CLR_START_ID, start);
+       falcon_write(efx, &buf_tbl_upd, BUF_TBL_UPD_REG_KER);
+}
+
+/*
+ * Allocate a new Falcon special buffer
+ *
+ * This allocates memory for a new buffer, clears it and allocates a
+ * new buffer ID range.  It does not write into Falcon's buffer table.
+ *
+ * This call will allocate 4kB buffers, since Falcon can't use 8kB
+ * buffers for event queues and descriptor rings.  It will always
+ * allocate an even number of 4kB buffers, since when we're in
+ * half-entry mode for the buffer table we can only deal with pairs of
+ * buffers.
+ */
+static int falcon_alloc_special_buffer(struct efx_nic *efx,
+                                      struct efx_special_buffer *buffer,
+                                      unsigned int len)
+{
+       struct falcon_nic_data *nic_data = efx->nic_data;
+
+       /* Round size up to an 8kB boundary (i.e. pairs of 4kB buffers) */
+       len = (len + 8192 - 1) & ~(8192 - 1);
+
+       /* Allocate buffer as consistent PCI DMA space */
+       buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
+                                           &buffer->dma_addr);
+       if (!buffer->addr)
+               return -ENOMEM;
+       buffer->len = len;
+       buffer->entries = len / 4096;
+       BUG_ON(buffer->dma_addr & (FALCON_BUF_ALIGN - 1));
+
+       /* All zeros is a potentially valid event so memset to 0xff */
+       memset(buffer->addr, 0xff, len);
+
+       /* Select new buffer ID */
+       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,
+               buffer->index + buffer->entries - 1,
+               (unsigned long long)buffer->dma_addr, len,
+               buffer->addr, virt_to_phys(buffer->addr));
+
+       return 0;
+}
+
+/*
+ * Initialise a Falcon special buffer
+ *
+ * This will define a buffer (previously allocated via
+ * falcon_alloc_special_buffer()) in Falcon's buffer table, allowing
+ * it to be used for event queues, descriptor rings etc.
+ */
+static int falcon_init_special_buffer(struct efx_nic *efx,
+                                     struct efx_special_buffer *buffer)
+{
+       EFX_BUG_ON_PARANOID(!buffer->addr);
+
+       /* Write buffer descriptors to NIC */
+       return falcon_pin_special_buffer_full(efx, buffer);
+}
+
+/* Unmaps a buffer from Falcon and clears the buffer table
+ * entries */
+static void falcon_fini_special_buffer(struct efx_nic *efx,
+                                      struct efx_special_buffer *buffer)
+{
+
+       if (!buffer->entries)
+               return;
+
+       falcon_clear_special_buffer_full(efx, buffer);
+}
+
+/* Release the buffer memory. */
+static void falcon_free_special_buffer(struct efx_nic *efx,
+                                      struct efx_special_buffer *buffer)
+{
+       if (!buffer->addr)
+               return;
+
+       EFX_LOG(efx, "deallocating special buffers %d-%d at %llx+%x "
+               "(virt %p phys %lx)\n", buffer->index,
+               buffer->index + buffer->entries - 1,
+               (unsigned long long)buffer->dma_addr, buffer->len,
+               buffer->addr, virt_to_phys(buffer->addr));
+
+       pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
+                           buffer->dma_addr);
+       buffer->addr = NULL;
+       buffer->entries = 0;
+}
+
+/**************************************************************************
+ *
+ * Falcon generic buffer handling
+ * These buffers are used for interrupt status and MAC stats
+ *
+ **************************************************************************/
+
+static int falcon_alloc_buffer(struct efx_nic *efx,
+                              struct efx_buffer *buffer, unsigned int len)
+{
+       buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
+                                           &buffer->dma_addr);
+       if (!buffer->addr)
+               return -ENOMEM;
+       buffer->len = len;
+       memset(buffer->addr, 0, len);
+       return 0;
+}
+
+static void falcon_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
+{
+       if (buffer->addr) {
+               pci_free_consistent(efx->pci_dev, buffer->len,
+                                   buffer->addr, buffer->dma_addr);
+               buffer->addr = NULL;
+       }
+}
+
+/**************************************************************************
+ *
+ * Falcon TX path
+ *
+ **************************************************************************/
+
+/* Returns a pointer to the specified transmit descriptor in the TX
+ * descriptor queue belonging to the specified channel.
+ */
+static inline efx_qword_t *falcon_tx_desc(struct efx_tx_queue *tx_queue,
+                                              unsigned int index)
+{
+       return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
+}
+
+/* Update TX descriptor write pointer
+ * This writes to the TX_DESC_WPTR register for the specified
+ * channel's transmit descriptor ring.
+ */
+static inline void falcon_notify_tx_desc(struct efx_tx_queue *tx_queue)
+{
+       unsigned write_ptr;
+       efx_dword_t reg;
+
+       write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
+       EFX_POPULATE_DWORD_1(reg, TX_DESC_WPTR_DWORD, write_ptr);
+       falcon_writel_page(tx_queue->efx, &reg,
+                          TX_DESC_UPD_REG_KER_DWORD, tx_queue->queue);
+}
+
+
+/* For each entry inserted into the software descriptor ring, create a
+ * descriptor in the hardware TX descriptor ring (in host memory), and
+ * write a doorbell.
+ */
+#if defined(EFX_USE_FASTCALL)
+void fastcall falcon_push_buffers(struct efx_tx_queue *tx_queue)
+#else
+void falcon_push_buffers(struct efx_tx_queue *tx_queue)
+#endif
+{
+
+       struct efx_tx_buffer *buffer;
+       efx_qword_t *txd;
+       unsigned write_ptr;
+
+       BUG_ON(tx_queue->write_count == tx_queue->insert_count);
+
+       do {
+               write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK;
+               buffer = &tx_queue->buffer[write_ptr];
+               txd = falcon_tx_desc(tx_queue, write_ptr);
+               ++tx_queue->write_count;
+
+               /* Create TX descriptor ring entry */
+               EFX_POPULATE_QWORD_5(*txd,
+                                    TX_KER_PORT, 0,
+                                    TX_KER_CONT, buffer->continuation,
+                                    TX_KER_BYTE_CNT, buffer->len,
+                                    TX_KER_BUF_REGION, 0,
+                                    TX_KER_BUF_ADR, buffer->dma_addr);
+       } while (tx_queue->write_count != tx_queue->insert_count);
+
+       wmb(); /* Ensure descriptors are written before they are fetched */
+       falcon_notify_tx_desc(tx_queue);
+}
+
+/* Allocate hardware resources for a TX queue */
+int falcon_probe_tx(struct efx_tx_queue *tx_queue)
+{
+       struct efx_nic *efx = tx_queue->efx;
+       struct falcon_nic_data *nic_data = efx->nic_data;
+       int rc;
+
+       rc = falcon_alloc_special_buffer(efx, &tx_queue->txd,
+                                        FALCON_TXD_RING_SIZE *
+                                        sizeof(efx_qword_t));
+       if (rc)
+               return rc;
+
+       nic_data->resources.txq_min = max(nic_data->resources.txq_min,
+                                         (unsigned)tx_queue->queue + 1);
+
+       return 0;
+}
+
+/* Prepare channel's TX datapath. */
+int falcon_init_tx(struct efx_tx_queue *tx_queue)
+{
+       efx_oword_t tx_desc_ptr;
+       struct efx_nic *efx = tx_queue->efx;
+       int rc;
+
+       /* Pin TX descriptor ring */
+       rc = falcon_init_special_buffer(efx, &tx_queue->txd);
+       if (rc)
+               return rc;
+
+       /* Push TX descriptor ring to card */
+       EFX_POPULATE_OWORD_10(tx_desc_ptr,
+                             TX_DESCQ_EN, 1,
+                             TX_ISCSI_DDIG_EN, 0,
+                             TX_ISCSI_HDIG_EN, 0,
+                             TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
+                             TX_DESCQ_EVQ_ID, tx_queue->channel->evqnum,
+                             TX_DESCQ_OWNER_ID, 0,
+                             TX_DESCQ_LABEL, tx_queue->queue,
+                             TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER,
+                             TX_DESCQ_TYPE, 0, /* kernel queue */
+                             TX_NON_IP_DROP_DIS_B0, 1);
+
+       if (FALCON_REV(efx) >= FALCON_REV_B0) {
+               int csum = !(efx->net_dev->features & NETIF_F_IP_CSUM);
+               EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, csum);
+               EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, csum);
+       }
+
+       falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+                          tx_queue->queue);
+
+       if (FALCON_REV(efx) < FALCON_REV_B0) {
+               efx_oword_t reg;
+
+               /* Only 128 bits in this register */
+               BUG_ON(tx_queue->queue >= 128);
+
+               falcon_read(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
+               if (efx->net_dev->features & NETIF_F_IP_CSUM)
+                       clear_bit_le(tx_queue->queue, (void *)&reg);
+               else
+                       set_bit_le(tx_queue->queue, (void *)&reg);
+               falcon_write(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
+       }
+
+       return 0;
+}
+
+static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
+{
+       struct efx_nic *efx = tx_queue->efx;
+       struct efx_channel *channel = &efx->channel[0];
+       efx_oword_t tx_flush_descq;
+       unsigned int read_ptr, i;
+
+       /* Post a flush command */
+       EFX_POPULATE_OWORD_2(tx_flush_descq,
+                            TX_FLUSH_DESCQ_CMD, 1,
+                            TX_FLUSH_DESCQ, tx_queue->queue);
+       falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER);
+       msleep(FALCON_FLUSH_TIMEOUT);
+
+       /* If the NIC is resetting then don't bother checking */
+       if (EFX_WORKAROUND_7803(efx) || (efx->state == STATE_RESETTING))
+               return 0;
+
+       /* Look for a flush completed event */
+       read_ptr = channel->eventq_read_ptr;
+       for (i = 0; i < FALCON_EVQ_SIZE; ++i) {
+               efx_qword_t *event = falcon_event(channel, read_ptr);
+               int ev_code, ev_sub_code, ev_queue;
+               if (!falcon_event_present(event))
+                       break;
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>