]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Wed, 22 Mar 2006 18:47:24 +0000 (10:47 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 22 Mar 2006 18:47:24 +0000 (10:47 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (138 commits)
  [SCSI] libata: implement minimal transport template for ->eh_timed_out
  [SCSI] eliminate rphy allocation in favour of expander/end device allocation
  [SCSI] convert mptsas over to end_device/expander allocations
  [SCSI] allow displaying and setting of cache type via sysfs
  [SCSI] add scsi_mode_select to scsi_lib.c
  [SCSI] 3ware 9000 add big endian support
  [SCSI] qla2xxx: update MAINTAINERS
  [SCSI] scsi: move target_destroy call
  [SCSI] fusion - bump version
  [SCSI] fusion - expander hotplug suport in mptsas module
  [SCSI] fusion - exposing raid components in mptsas
  [SCSI] fusion - memory leak, and initializing fields
  [SCSI] fusion - exclosure misspelled
  [SCSI] fusion - cleanup mptsas event handling functions
  [SCSI] fusion - removing target_id/bus_id from the VirtDevice structure
  [SCSI] fusion - static fix's
  [SCSI] fusion - move some debug firmware event debug msgs to verbose level
  [SCSI] fusion - loginfo header update
  [SCSI] add scsi_reprobe_device
  [SCSI] megaraid_sas: fix extended timeout handling
  ...

175 files changed:
Documentation/networking/e100.txt
Documentation/networking/e1000.txt
MAINTAINERS
arch/alpha/mm/init.c
arch/arm/mm/consistent.c
arch/arm/mm/init.c
arch/arm26/mm/init.c
arch/cris/mm/init.c
arch/frv/kernel/frv_ksyms.c
arch/frv/mm/dma-alloc.c
arch/frv/mm/init.c
arch/h8300/kernel/h8300_ksyms.c
arch/h8300/mm/init.c
arch/i386/kernel/efi.c
arch/i386/kernel/smp.c
arch/i386/kernel/sys_i386.c
arch/i386/kernel/timers/timer_hpet.c
arch/i386/kernel/timers/timer_tsc.c
arch/i386/mm/hugetlbpage.c
arch/i386/mm/init.c
arch/i386/mm/pageattr.c
arch/ia64/Kconfig
arch/ia64/configs/tiger_defconfig
arch/ia64/kernel/acpi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/signal.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/hugetlbpage.c
arch/ia64/mm/init.c
arch/ia64/sn/kernel/Makefile
arch/ia64/sn/kernel/pio_phys.S [new file with mode: 0644]
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/xpc_channel.c
arch/ia64/sn/kernel/xpc_main.c
arch/ia64/sn/kernel/xpc_partition.c
arch/ia64/sn/pci/tioce_provider.c
arch/m32r/mm/init.c
arch/m68k/mm/init.c
arch/m68k/mm/memory.c
arch/m68k/mm/motorola.c
arch/m68knommu/kernel/m68k_ksyms.c
arch/m68knommu/mm/init.c
arch/mips/arc/memory.c
arch/mips/dec/prom/memory.c
arch/mips/mips-boards/generic/memory.c
arch/mips/mips-boards/sim/sim_mem.c
arch/mips/mm/init.c
arch/mips/sgi-ip27/ip27-memory.c
arch/parisc/mm/init.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/platforms/cell/setup.c
arch/ppc/kernel/dma-mapping.c
arch/ppc/mm/init.c
arch/s390/mm/init.c
arch/sh/mm/consistent.c
arch/sh/mm/hugetlbpage.c
arch/sh/mm/init.c
arch/sh64/mm/hugetlbpage.c
arch/sh64/mm/init.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/mm/init.c
arch/sparc64/mm/hugetlbpage.c
arch/sparc64/mm/init.c
arch/um/kernel/mem.c
arch/um/kernel/physmem.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/mm/init.c
arch/x86_64/mm/pageattr.c
arch/xtensa/mm/init.c
arch/xtensa/mm/pgtable.c
drivers/char/snsc.h
drivers/char/snsc_event.c
drivers/char/tb0219.c
drivers/char/vr41xx_giu.c
drivers/char/vr41xx_rtc.c
drivers/char/watchdog/mv64x60_wdt.c
drivers/firmware/dcdbas.c
drivers/md/dm.c
drivers/media/dvb/bt8xx/Makefile
drivers/net/mv643xx_eth.h
drivers/net/pcnet32.c
drivers/net/skfp/fplustm.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/sky2.c
drivers/net/sky2.h
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/sg.c
drivers/serial/Kconfig
drivers/serial/serial_txx9.c
drivers/serial/vr41xx_siu.c
drivers/sn/ioc4.c
drivers/video/acornfb.c
drivers/video/i810/i810_main.c
fs/9p/vfs_inode.c
fs/buffer.c
fs/hugetlbfs/inode.c
fs/ocfs2/super.c
fs/ramfs/file-nommu.c
fs/xfs/linux-2.6/xfs_buf.c
include/asm-i386/acpi.h
include/asm-i386/pgtable.h
include/asm-ia64/intel_intrin.h
include/asm-ia64/machvec.h
include/asm-ia64/machvec_sn2.h
include/asm-ia64/mca.h
include/asm-ia64/mutex.h
include/asm-ia64/page.h
include/asm-ia64/pgtable.h
include/asm-ia64/processor.h
include/asm-ia64/signal.h
include/asm-ia64/sn/addrs.h
include/asm-ia64/sn/rw_mmr.h
include/asm-ia64/sn/tioce.h
include/asm-ia64/sn/xpc.h
include/asm-ia64/system.h
include/asm-ia64/thread_info.h
include/asm-powerpc/pgtable.h
include/asm-s390/pgalloc.h
include/asm-sh64/pgalloc.h
include/asm-x86_64/pgtable.h
include/linux/hugetlb.h
include/linux/migrate.h [new file with mode: 0644]
include/linux/mm.h
include/linux/mm_inline.h
include/linux/page-flags.h
include/linux/rtc.h
include/linux/slab.h
include/linux/smp.h
include/linux/swap.h
kernel/fork.c
kernel/sched.c
kernel/softirq.c
lib/string.c
mm/Kconfig
mm/Makefile
mm/filemap.c
mm/hugetlb.c
mm/internal.h
mm/memory.c
mm/mempolicy.c
mm/mempool.c
mm/migrate.c [new file with mode: 0644]
mm/mmap.c
mm/mprotect.c
mm/nommu.c
mm/page_alloc.c
mm/readahead.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c
security/keys/process_keys.c
security/selinux/hooks.c
security/selinux/selinuxfs.c
security/selinux/ss/services.c

index 4ef9f7cd5dc33ac4de83bb49fe952a90cb190dc8..944aa55e79f83386ce8c92599d8c9c989f5f6065 100644 (file)
@@ -1,16 +1,17 @@
 Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
 ==============================================================
 
-November 17, 2004
-
+November 15, 2005
 
 Contents
 ========
 
 - In This Release
 - Identifying Your Adapter
+- Building and Installation
 - Driver Configuration Parameters
 - Additional Configurations
+- Known Issues
 - Support
 
 
@@ -18,18 +19,30 @@ In This Release
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
-Adapters, version 3.3.x.  This driver supports 2.4.x and 2.6.x kernels. 
+Adapters. This driver includes support for Itanium(R)2-based systems.
+
+For questions related to hardware requirements, refer to the documentation
+supplied with your Intel PRO/100 adapter.
+
+The following features are now available in supported kernels:
+ - Native VLANs
+ - Channel Bonding (teaming)
+ - SNMP
+
+Channel Bonding documentation can be found in the Linux kernel source:
+/Documentation/networking/bonding.txt
+
 
 Identifying Your Adapter
 ========================
 
-For more information on how to identify your adapter, go to the Adapter & 
+For more information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
   http://support.intel.com/support/network/adapter/pro100/21397.htm
 
-For the latest Intel network drivers for Linux, refer to the following 
-website. In the search field, enter your adapter name or type, or use the 
+For the latest Intel network drivers for Linux, refer to the following
+website. In the search field, enter your adapter name or type, or use the
 networking link on the left to search for your adapter:
 
   http://downloadfinder.intel.com/scripts-df/support_intel.asp
@@ -40,73 +53,75 @@ Driver Configuration Parameters
 The default value for each parameter is generally the recommended setting,
 unless otherwise noted.
 
-Rx Descriptors: Number of receive descriptors. A receive descriptor is a data 
-   structure that describes a receive buffer and its attributes to the network 
-   controller. The data in the descriptor is used by the controller to write 
-   data from the controller to host memory. In the 3.0.x driver the valid
-   range for this parameter is 64-256. The default value is 64. This parameter 
-   can be changed using the command 
+Rx Descriptors: Number of receive descriptors. A receive descriptor is a data
+   structure that describes a receive buffer and its attributes to the network
+   controller. The data in the descriptor is used by the controller to write
+   data from the controller to host memory. In the 3.x.x driver the valid range
+   for this parameter is 64-256. The default value is 64. This parameter can be
+   changed using the command:
+
    ethtool -G eth? rx n, where n is the number of desired rx descriptors.
 
-Tx Descriptors: Number of transmit descriptors. A transmit descriptor is a
-   data structure that describes a transmit buffer and its attributes to the
-   network controller. The data in the descriptor is used by the controller to 
-   read data from the host memory to the controller. In the 3.0.x driver the 
-   valid range for this parameter is 64-256. The default value is 64. This 
-   parameter can be changed using the command 
+Tx Descriptors: Number of transmit descriptors. A transmit descriptor is a data
+   structure that describes a transmit buffer and its attributes to the network
+   controller. The data in the descriptor is used by the controller to read
+   data from the host memory to the controller. In the 3.x.x driver the valid
+   range for this parameter is 64-256. The default value is 64. This parameter
+   can be changed using the command:
 
    ethtool -G eth? tx n, where n is the number of desired tx descriptors.
 
-Speed/Duplex: The driver auto-negotiates the link speed and duplex settings by 
-   default. Ethtool can be used as follows to force speed/duplex. 
+Speed/Duplex: The driver auto-negotiates the link speed and duplex settings by
+   default. Ethtool can be used as follows to force speed/duplex.
 
    ethtool -s eth?  autoneg off speed {10|100} duplex {full|half}
 
    NOTE: setting the speed/duplex to incorrect values will cause the link to
    fail.
 
-Event Log Message Level:  The driver uses the message level flag to log events 
-   to syslog. The message level can be set at driver load time. It can also be 
-   set using the command
+Event Log Message Level:  The driver uses the message level flag to log events
+   to syslog. The message level can be set at driver load time. It can also be
+   set using the command:
 
    ethtool -s eth? msglvl n
 
+
 Additional Configurations
 =========================
 
   Configuring the Driver on Different Distributions
   -------------------------------------------------
 
-  Configuring a network driver to load properly when the system is started is 
-  distribution dependent. Typically, the configuration process involves adding 
-  an alias line to /etc/modules.conf as well as editing other system startup 
-  scripts and/or configuration files.  Many popular Linux distributions ship 
-  with tools to make these changes for you. To learn the proper way to 
-  configure a network device for your system, refer to your distribution 
-  documentation. If during this process you are asked for the driver or module 
-  name, the name for the Linux Base Driver for the Intel PRO/100 Family of 
-  Adapters is e100.
+  Configuring a network driver to load properly when the system is started is
+  distribution dependent. Typically, the configuration process involves adding
+  an alias line to /etc/modules.conf or /etc/modprobe.conf as well as editing
+  other system startup scripts and/or configuration files.  Many popular Linux
+  distributions ship with tools to make these changes for you. To learn the
+  proper way to configure a network device for your system, refer to your
+  distribution documentation.  If during this process you are asked for the
+  driver or module name, the name for the Linux Base Driver for the Intel
+  PRO/100 Family of Adapters is e100.
 
-  As an example, if you install the e100 driver for two PRO/100 adapters 
-  (eth0 and eth1), add the following to modules.conf:
+  As an example, if you install the e100 driver for two PRO/100 adapters
+  (eth0 and eth1), add the following to modules.conf or modprobe.conf:
 
        alias eth0 e100
        alias eth1 e100
 
   Viewing Link Messages
   ---------------------
-  In order to see link messages and other Intel driver information on your 
-  console, you must set the dmesg level up to six. This can be done by 
-  entering the following on the command line before loading the e100 driver: 
+  In order to see link messages and other Intel driver information on your
+  console, you must set the dmesg level up to six. This can be done by
+  entering the following on the command line before loading the e100 driver:
 
        dmesg -n 8
 
-  If you wish to see all messages issued by the driver, including debug 
+  If you wish to see all messages issued by the driver, including debug
   messages, set the dmesg level to eight.
 
   NOTE: This setting is not saved across reboots.
 
+
   Ethtool
   -------
 
@@ -114,29 +129,27 @@ Additional Configurations
   diagnostics, as well as displaying statistical information.  Ethtool
   version 1.6 or later is required for this functionality.
 
-  The latest release of ethtool can be found at:
-  http://sf.net/projects/gkernel.  
+  The latest release of ethtool can be found from
+  http://sourceforge.net/projects/gkernel.
 
-  NOTE: This driver uses mii support from the kernel. As a result, when 
-  there is no link, ethtool will report speed/duplex to be 10/half.
+  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
+  for a more complete ethtool feature set can be enabled by upgrading
+  ethtool to ethtool-1.8.1.
 
-  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support 
-  for a more complete ethtool feature set can be enabled by upgrading 
-  ethtool to ethtool-1.8.1. 
 
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is provided through the Ethtool* utility. Ethtool is included with Red 
-  Hat* 8.0. For other Linux distributions, download and install Ethtool from 
-  the following website: http://sourceforge.net/projects/gkernel. 
+  WoL is provided through the Ethtool* utility. Ethtool is included with Red
+  Hat* 8.0. For other Linux distributions, download and install Ethtool from
+  the following website: http://sourceforge.net/projects/gkernel.
 
-  For instructions on enabling WoL with Ethtool, refer to the Ethtool man
-  page.
+  For instructions on enabling WoL with Ethtool, refer to the Ethtool man page.
 
   WoL will be enabled on the system during the next shut down or reboot. For
-  this driver version, in order to enable WoL, the e100 driver must be 
+  this driver version, in order to enable WoL, the e100 driver must be
   loaded when shutting down or rebooting the system.
 
+
   NAPI
   ----
 
@@ -144,6 +157,25 @@ Additional Configurations
 
   See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
 
+  Multiple Interfaces on Same Ethernet Broadcast Network
+  ------------------------------------------------------
+
+  Due to the default ARP behavior on Linux, it is not possible to have
+  one system on two IP networks in the same Ethernet broadcast domain
+  (non-partitioned switch) behave as expected. All Ethernet interfaces
+  will respond to IP traffic for any IP address assigned to the system.
+  This results in unbalanced receive traffic.
+
+  If you have multiple interfaces in a server, either turn on ARP
+  filtering by
+
+  (1) entering: echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
+      (this only works if your kernel's version is higher than 2.4.5), or
+
+  (2) installing the interfaces in separate broadcast domains (either
+      in different switches or in a switch partitioned to VLANs).
+
+
 Support
 =======
 
@@ -151,20 +183,24 @@ For general information, go to the Intel support website at:
 
     http://support.intel.com
 
+    or the Intel Wired Networking project hosted by Sourceforge at:
+
+    http://sourceforge.net/projects/e1000
+
 If an issue is identified with the released source code on the supported
-kernel with a supported adapter, email the specific information related to 
-the issue to linux.nics@intel.com.
+kernel with a supported adapter, email the specific information related to the
+issue to e1000-devel@lists.sourceforge.net.
 
 
 License
 =======
 
-This software program is released under the terms of a license agreement 
-between you ('Licensee') and Intel. Do not use or load this software or any 
-associated materials (collectively, the 'Software') until you have carefully 
-read the full terms and conditions of the LICENSE located in this software 
-package. By loading or using the Software, you agree to the terms of this 
-Agreement. If you do not agree with the terms of this Agreement, do not 
-install or use the Software.
+This software program is released under the terms of a license agreement
+between you ('Licensee') and Intel. Do not use or load this software or any
+associated materials (collectively, the 'Software') until you have carefully
+read the full terms and conditions of the file COPYING located in this software
+package. By loading or using the Software, you agree to the terms of this
+Agreement. If you do not agree with the terms of this Agreement, do not install
+or use the Software.
 
 * Other names and brands may be claimed as the property of others.
index 2ebd4058d46d4b3b17df8d2b04310a47ffd1baf4..71fe15af356cda609a2a0abae7b11bff1be1df0a 100644 (file)
@@ -1,7 +1,7 @@
 Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
 ===============================================================
 
-November 17, 2004
+November 15, 2005
 
 
 Contents
@@ -20,254 +20,316 @@ In This Release
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
-of Adapters, version 5.x.x.  
+of Adapters.  This driver includes support for Itanium(R)2-based systems.
 
-For questions related to hardware requirements, refer to the documentation 
-supplied with your Intel PRO/1000 adapter. All hardware requirements listed 
+For questions related to hardware requirements, refer to the documentation
+supplied with your Intel PRO/1000 adapter. All hardware requirements listed
 apply to use with Linux.
 
-Native VLANs are now available with supported kernels.
+The following features are now available in supported kernels:
+ - Native VLANs
+ - Channel Bonding (teaming)
+ - SNMP
+
+Channel Bonding documentation can be found in the Linux kernel source:
+/Documentation/networking/bonding.txt
+
+The driver information previously displayed in the /proc filesystem is not
+supported in this release.  Alternatively, you can use ethtool (version 1.6
+or later), lspci, and ifconfig to obtain the same information.
+
+Instructions on updating ethtool can be found in the section "Additional
+Configurations" later in this document.
+
 
 Identifying Your Adapter
 ========================
 
-For more information on how to identify your adapter, go to the Adapter & 
+For more information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
     http://support.intel.com/support/network/adapter/pro100/21397.htm
 
-For the latest Intel network drivers for Linux, refer to the following 
-website. In the search field, enter your adapter name or type, or use the 
+For the latest Intel network drivers for Linux, refer to the following
+website. In the search field, enter your adapter name or type, or use the
 networking link on the left to search for your adapter:
 
     http://downloadfinder.intel.com/scripts-df/support_intel.asp
 
-Command Line Parameters
-=======================
 
-If the driver is built as a module, the  following optional parameters are 
-used by entering them on the command line with the modprobe or insmod command
-using this syntax:
+Command Line Parameters =======================
+
+If the driver is built as a module, the  following optional parameters
+are used by entering them on the command line with the modprobe or insmod
+command using this syntax:
 
      modprobe e1000 [<option>=<VAL1>,<VAL2>,...]
 
-     insmod e1000 [<option>=<VAL1>,<VAL2>,...] 
+     insmod e1000 [<option>=<VAL1>,<VAL2>,...]
 
 For example, with two PRO/1000 PCI adapters, entering:
 
      insmod e1000 TxDescriptors=80,128
 
-loads the e1000 driver with 80 TX descriptors for the first adapter and 128 TX 
-descriptors for the second adapter.
+loads the e1000 driver with 80 TX descriptors for the first adapter and 128
+TX descriptors for the second adapter.
 
 The default value for each parameter is generally the recommended setting,
-unless otherwise noted. Also, if the driver is statically built into the
-kernel, the driver is loaded with the default values for all the parameters.
-Ethtool can be used to change some of the parameters at runtime.
+unless otherwise noted.
+
+NOTES:  For more information about the AutoNeg, Duplex, and Speed
+        parameters, see the "Speed and Duplex Configuration" section in
+        this document.
 
-    NOTES: For more information about the AutoNeg, Duplex, and Speed
-           parameters, see the "Speed and Duplex Configuration" section in 
-           this document.
+        For more information about the InterruptThrottleRate,
+        RxIntDelay, TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay
+        parameters, see the application note at:
+        http://www.intel.com/design/network/applnots/ap450.htm
 
-           For more information about the InterruptThrottleRate, RxIntDelay, 
-           TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay parameters, see the 
-           application note at:
-           http://www.intel.com/design/network/applnots/ap450.htm
+        A descriptor describes a data buffer and attributes related to
+        the data buffer. This information is accessed by the hardware.
 
-           A descriptor describes a data buffer and attributes related to the 
-           data buffer. This information is accessed by the hardware.
 
-AutoNeg (adapters using copper connections only)
-Valid Range: 0x01-0x0F, 0x20-0x2F
+AutoNeg
+-------
+(Supported only on adapters with copper connections)
+Valid Range:   0x01-0x0F, 0x20-0x2F
 Default Value: 0x2F
-    This parameter is a bit mask that specifies which speed and duplex
-    settings the board advertises. When this parameter is used, the Speed and
-    Duplex parameters must not be specified.
-    NOTE: Refer to the Speed and Duplex section of this readme for more 
-          information on the AutoNeg parameter.  
-
-Duplex (adapters using copper connections only)
-Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full)
+
+This parameter is a bit mask that specifies which speed and duplex
+settings the board advertises. When this parameter is used, the Speed
+and Duplex parameters must not be specified.
+
+NOTE:  Refer to the Speed and Duplex section of this readme for more
+       information on the AutoNeg parameter.
+
+
+Duplex
+------
+(Supported only on adapters with copper connections)
+Valid Range:   0-2 (0=auto-negotiate, 1=half, 2=full)
 Default Value: 0
-    Defines the direction in which data is allowed to flow. Can be either one 
-    or two-directional. If both Duplex and the link partner are set to auto-
-    negotiate, the board auto-detects the correct duplex. If the link partner
-    is forced (either full or half), Duplex defaults to half-duplex.
+
+Defines the direction in which data is allowed to flow. Can be either
+one or two-directional. If both Duplex and the link partner are set to
+auto-negotiate, the board auto-detects the correct duplex. If the link
+partner is forced (either full or half), Duplex defaults to half-duplex.
+
 
 FlowControl
-Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
-Default: Read flow control settings from the EEPROM
-    This parameter controls the automatic generation(Tx) and response(Rx) to 
-    Ethernet PAUSE frames.
+----------
+Valid Range:   0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
+Default Value: Reads flow control settings from the EEPROM
+
+This parameter controls the automatic generation(Tx) and response(Rx)
+to Ethernet PAUSE frames.
+
 
 InterruptThrottleRate
-Valid Range: 100-100000 (0=off, 1=dynamic)
+---------------------
+(not supported on Intel 82542, 82543 or 82544-based adapters)
+Valid Range:   100-100000 (0=off, 1=dynamic)
 Default Value: 8000
-    This value represents the maximum number of interrupts per second the 
-    controller generates. InterruptThrottleRate is another setting used in 
-    interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust 
-    InterruptThrottleRate based on the current traffic load.
-Un-supported Adapters: InterruptThrottleRate is NOT supported by 82542, 82543
-    or 82544-based adapters.
-
-    NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and 
-          RxAbsIntDelay parameters. In other words, minimizing the receive 
-          and/or transmit absolute delays does not force the controller to 
-          generate more interrupts than what the Interrupt Throttle Rate 
-          allows.
-    CAUTION: If you are using the Intel PRO/1000 CT Network Connection 
-             (controller 82547), setting InterruptThrottleRate to a value 
-             greater than 75,000, may hang (stop transmitting) adapters under 
-             certain network conditions. If this occurs a NETDEV WATCHDOG 
-             message is logged in the system event log. In addition, the 
-             controller is automatically reset, restoring the network 
-             connection. To eliminate the potential for the hang, ensure 
-             that InterruptThrottleRate is set no greater than 75,000 and is 
-             not set to 0.
-    NOTE: When e1000 is loaded with default settings and multiple adapters are 
-          in use simultaneously, the CPU utilization may increase non-linearly. 
-          In order to limit the CPU utilization without impacting the overall 
-          throughput, we recommend that you load the driver as follows:
-
-              insmod e1000.o InterruptThrottleRate=3000,3000,3000
-
-          This sets the InterruptThrottleRate to 3000 interrupts/sec for the 
-          first, second, and third instances of the driver. The range of 2000 to 
-          3000 interrupts per second works on a majority of systems and is a 
-          good starting point, but the optimal value will be platform-specific. 
-          If CPU utilization is not a concern, use RX_POLLING (NAPI) and default 
-          driver settings.
+
+This value represents the maximum number of interrupts per second the
+controller generates. InterruptThrottleRate is another setting used in
+interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust
+InterruptThrottleRate based on the current traffic load.
+
+NOTE:  InterruptThrottleRate takes precedence over the TxAbsIntDelay and
+       RxAbsIntDelay parameters. In other words, minimizing the receive
+       and/or transmit absolute delays does not force the controller to
+       generate more interrupts than what the Interrupt Throttle Rate
+       allows.
+
+CAUTION:  If you are using the Intel PRO/1000 CT Network Connection
+          (controller 82547), setting InterruptThrottleRate to a value
+          greater than 75,000, may hang (stop transmitting) adapters
+          under certain network conditions. If this occurs a NETDEV
+          WATCHDOG message is logged in the system event log. In
+          addition, the controller is automatically reset, restoring
+          the network connection. To eliminate the potential for the
+          hang, ensure that InterruptThrottleRate is set no greater
+          than 75,000 and is not set to 0.
+
+NOTE:  When e1000 is loaded with default settings and multiple adapters
+       are in use simultaneously, the CPU utilization may increase non-
+       linearly. In order to limit the CPU utilization without impacting
+       the overall throughput, we recommend that you load the driver as
+       follows:
+
+           insmod e1000.o InterruptThrottleRate=3000,3000,3000
+
+       This sets the InterruptThrottleRate to 3000 interrupts/sec for
+       the first, second, and third instances of the driver. The range
+       of 2000 to 3000 interrupts per second works on a majority of
+       systems and is a good starting point, but the optimal value will
+       be platform-specific. If CPU utilization is not a concern, use
+       RX_POLLING (NAPI) and default driver settings.
+
 
 RxDescriptors
-Valid Range: 80-256 for 82542 and 82543-based adapters
-             80-4096 for all other supported adapters
+-------------
+Valid Range:   80-256 for 82542 and 82543-based adapters
+               80-4096 for all other supported adapters
 Default Value: 256
-    This value is the number of receive descriptors allocated by the driver. 
-    Increasing this value allows the driver to buffer more incoming packets. 
-    Each descriptor is 16 bytes.  A receive buffer is allocated for each
-    descriptor and can either be 2048 or 4096 bytes long, depending on the MTU 
 
-    setting. An incoming packet can span one or more receive descriptors. 
-    The maximum MTU size is 16110.
+This value specifies the number of receive descriptors allocated by the
+driver. Increasing this value allows the driver to buffer more incoming
+packets.  Each descriptor is 16 bytes.  A receive buffer is also
+allocated for each descriptor and is 2048.
 
-    NOTE: MTU designates the frame size. It only needs to be set for Jumbo 
-          Frames.
-    NOTE: Depending on the available system resources, the request for a
-    higher number of receive descriptors may be denied.  In this case,
-    use a lower number.
 
 RxIntDelay
-Valid Range: 0-65535 (0=off)
+----------
+Valid Range:   0-65535 (0=off)
 Default Value: 0
-    This value delays the generation of receive interrupts in units of 1.024 
-    microseconds.  Receive interrupt reduction can improve CPU efficiency if 
-    properly tuned for specific network traffic. Increasing this value adds 
-    extra latency to frame reception and can end up decreasing the throughput 
-    of TCP traffic. If the system is reporting dropped receives, this value 
-    may be set too high, causing the driver to run out of available receive 
-    descriptors.
-
-    CAUTION: When setting RxIntDelay to a value other than 0, adapters may 
-             hang (stop transmitting) under certain network conditions. If 
-             this occurs a NETDEV WATCHDOG message is logged in the system
-             event log. In addition, the controller is automatically reset, 
-             restoring the network connection. To eliminate the potential for
-             the hang ensure that RxIntDelay is set to 0.
-
-RxAbsIntDelay (82540, 82545 and later adapters only)
-Valid Range: 0-65535 (0=off)
+
+This value delays the generation of receive interrupts in units of 1.024
+microseconds.  Receive interrupt reduction can improve CPU efficiency if
+properly tuned for specific network traffic. Increasing this value adds
+extra latency to frame reception and can end up decreasing the throughput
+of TCP traffic. If the system is reporting dropped receives, this value
+may be set too high, causing the driver to run out of available receive
+descriptors.
+
+CAUTION:  When setting RxIntDelay to a value other than 0, adapters may
+          hang (stop transmitting) under certain network conditions. If
+          this occurs a NETDEV WATCHDOG message is logged in the system
+          event log. In addition, the controller is automatically reset,
+          restoring the network connection. To eliminate the potential
+          for the hang ensure that RxIntDelay is set to 0.
+
+
+RxAbsIntDelay
+-------------
+(This parameter is supported only on 82540, 82545 and later adapters.)
+Valid Range:   0-65535 (0=off)
 Default Value: 128
-    This value, in units of 1.024 microseconds, limits the delay in which a 
-    receive interrupt is generated. Useful only if RxIntDelay is non-zero, 
-    this value ensures that an interrupt is generated after the initial 
-    packet is received within the set amount of time.  Proper tuning,
-    along with RxIntDelay, may improve traffic throughput in specific network
-    conditions.
-
-Speed (adapters using copper connections only)
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+receive interrupt is generated. Useful only if RxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is received within the set amount of time.  Proper tuning,
+along with RxIntDelay, may improve traffic throughput in specific network
+conditions.
+
+
+Speed
+-----
+(This parameter is supported only on adapters with copper connections.)
 Valid Settings: 0, 10, 100, 1000
-Default Value: 0 (auto-negotiate at all supported speeds)
-    Speed forces the line speed to the specified value in megabits per second
-    (Mbps). If this parameter is not specified or is set to 0 and the link 
-    partner is set to auto-negotiate, the board will auto-detect the correct 
-    speed. Duplex should also be set when Speed is set to either 10 or 100.
+Default Value:  0 (auto-negotiate at all supported speeds)
+
+Speed forces the line speed to the specified value in megabits per second
+(Mbps). If this parameter is not specified or is set to 0 and the link
+partner is set to auto-negotiate, the board will auto-detect the correct
+speed. Duplex should also be set when Speed is set to either 10 or 100.
+
 
 TxDescriptors
-Valid Range: 80-256 for 82542 and 82543-based adapters
-             80-4096 for all other supported adapters
+-------------
+Valid Range:   80-256 for 82542 and 82543-based adapters
+               80-4096 for all other supported adapters
 Default Value: 256
-    This value is the number of transmit descriptors allocated by the driver.
-    Increasing this value allows the driver to queue more transmits. Each 
-    descriptor is 16 bytes.
 
-    NOTE: Depending on the available system resources, the request for a
-    higher number of transmit descriptors may be denied.  In this case,
-    use a lower number.
+This value is the number of transmit descriptors allocated by the driver.
+Increasing this value allows the driver to queue more transmits. Each
+descriptor is 16 bytes.
+
+NOTE:  Depending on the available system resources, the request for a
+       higher number of transmit descriptors may be denied.  In this case,
+       use a lower number.
+
 
 TxIntDelay
-Valid Range: 0-65535 (0=off)
+----------
+Valid Range:   0-65535 (0=off)
 Default Value: 64
-    This value delays the generation of transmit interrupts in units of 
-    1.024 microseconds. Transmit interrupt reduction can improve CPU
-    efficiency if properly tuned for specific network traffic. If the
-    system is reporting dropped transmits, this value may be set too high
-    causing the driver to run out of available transmit descriptors.
-
-TxAbsIntDelay (82540, 82545 and later adapters only)
-Valid Range: 0-65535 (0=off)
+
+This value delays the generation of transmit interrupts in units of
+1.024 microseconds. Transmit interrupt reduction can improve CPU
+efficiency if properly tuned for specific network traffic. If the
+system is reporting dropped transmits, this value may be set too high
+causing the driver to run out of available transmit descriptors.
+
+
+TxAbsIntDelay
+-------------
+(This parameter is supported only on 82540, 82545 and later adapters.)
+Valid Range:   0-65535 (0=off)
 Default Value: 64
-    This value, in units of 1.024 microseconds, limits the delay in which a 
-    transmit interrupt is generated. Useful only if TxIntDelay is non-zero, 
-    this value ensures that an interrupt is generated after the initial 
-    packet is sent on the wire within the set amount of time.  Proper tuning,
-    along with TxIntDelay, may improve traffic throughput in specific 
-    network conditions.
-
-XsumRX (not available on the 82542-based adapter)
-Valid Range: 0-1
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+transmit interrupt is generated. Useful only if TxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is sent on the wire within the set amount of time.  Proper tuning,
+along with TxIntDelay, may improve traffic throughput in specific
+network conditions.
+
+XsumRX
+------
+(This parameter is NOT supported on the 82542-based adapter.)
+Valid Range:   0-1
 Default Value: 1
-    A value of '1' indicates that the driver should enable IP checksum
-    offload for received packets (both UDP and TCP) to the adapter hardware.
+
+A value of '1' indicates that the driver should enable IP checksum
+offload for received packets (both UDP and TCP) to the adapter hardware.
+
 
 Speed and Duplex Configuration
 ==============================
 
-Three keywords are used to control the speed and duplex configuration. These 
-keywords are Speed, Duplex, and AutoNeg.
+Three keywords are used to control the speed and duplex configuration.
+These keywords are Speed, Duplex, and AutoNeg.
 
-If the board uses a fiber interface, these keywords are ignored, and the 
+If the board uses a fiber interface, these keywords are ignored, and the
 fiber interface board only links at 1000 Mbps full-duplex.
 
 For copper-based boards, the keywords interact as follows:
 
-  The default operation is auto-negotiate. The board advertises all supported
-  speed and duplex combinations, and it links at the highest common speed and
-  duplex mode IF the link partner is set to auto-negotiate.
+  The default operation is auto-negotiate. The board advertises all
+  supported speed and duplex combinations, and it links at the highest
+  common speed and duplex mode IF the link partner is set to auto-negotiate.
 
-  If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps is
-  advertised (The 1000BaseT spec requires auto-negotiation.)
+  If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps
+  is advertised (The 1000BaseT spec requires auto-negotiation.)
 
   If Speed = 10 or 100, then both Speed and Duplex should be set. Auto-
-  negotiation is disabled, and the AutoNeg parameter is ignored. Partner SHOULD
-  also be forced.
+  negotiation is disabled, and the AutoNeg parameter is ignored. Partner
+  SHOULD also be forced.
+
+The AutoNeg parameter is used when more control is required over the
+auto-negotiation process.  It should be used when you wish to control which
+speed and duplex combinations are advertised during the auto-negotiation
+process.
+
+The parameter may be specified as either a decimal or hexidecimal value as
+determined by the bitmap below.
 
-The AutoNeg parameter is used when more control is required over the auto-
-negotiation process. When this parameter is used, Speed and Duplex parameters 
-must not be specified. The following table describes supported values for the 
-AutoNeg parameter:
+Bit position   7      6      5       4       3      2      1       0
+Decimal Value  128    64     32      16      8      4      2       1
+Hex value      80     40     20      10      8      4      2       1
+Speed (Mbps)   N/A    N/A    1000    N/A     100    100    10      10
+Duplex                       Full            Full   Half   Full    Half
 
-Speed (Mbps)                    1000      100    100    10     10
-Duplex                   Full      Full   Half   Full   Half
-Value (in base 16)       0x20      0x08   0x04   0x02   0x01
+Some examples of using AutoNeg:
 
-Example: insmod e1000 AutoNeg=0x03, loads e1000 and specifies (10 full duplex, 
-10 half duplex) for negotiation with the peer.
+  modprobe e1000 AutoNeg=0x01 (Restricts autonegotiation to 10 Half)
+  modprobe e1000 AutoNeg=1 (Same as above)
+  modprobe e1000 AutoNeg=0x02 (Restricts autonegotiation to 10 Full)
+  modprobe e1000 AutoNeg=0x03 (Restricts autonegotiation to 10 Half or 10 Full)
+  modprobe e1000 AutoNeg=0x04 (Restricts autonegotiation to 100 Half)
+  modprobe e1000 AutoNeg=0x05 (Restricts autonegotiation to 10 Half or 100
+  Half)
+  modprobe e1000 AutoNeg=0x020 (Restricts autonegotiation to 1000 Full)
+  modprobe e1000 AutoNeg=32 (Same as above)
 
-Note that setting AutoNeg does not guarantee that the board will link at the 
-highest specified speed or duplex mode, but the board will link at the 
-highest possible speed/duplex of the link partner IF the link partner is also
-set to auto-negotiate. If the link partner is forced speed/duplex, the 
-adapter MUST be forced to the same speed/duplex.
+Note that when this parameter is used, Speed and Duplex must not be specified.
+
+If the link partner is forced to a specific speed and duplex, then this
+parameter should not be used.  Instead, use the Speed and Duplex parameters
+previously mentioned to force the adapter to the same speed and duplex.
 
 
 Additional Configurations
@@ -276,19 +338,19 @@ Additional Configurations
   Configuring the Driver on Different Distributions
   -------------------------------------------------
 
-  Configuring a network driver to load properly when the system is started is
-  distribution dependent. Typically, the configuration process involves adding
-  an alias line to /etc/modules.conf as well as editing other system startup 
-  scripts and/or configuration files. Many popular Linux distributions ship 
-  with tools to make these changes for you. To learn the proper way to 
-  configure a network device for your system, refer to your distribution 
-  documentation. If during this process you are asked for the driver or module 
-  name, the name for the Linux Base Driver for the Intel PRO/1000 Family of 
-  Adapters is e1000.
+  Configuring a network driver to load properly when the system is started
+  is distribution dependent. Typically, the configuration process involves
+  adding an alias line to /etc/modules.conf or /etc/modprobe.conf as well
+  as editing other system startup scripts and/or configuration files. Many
+  popular Linux distributions ship with tools to make these changes for you.
+  To learn the proper way to configure a network device for your system,
+  refer to your distribution documentation. If during this process you are
+  asked for the driver or module name, the name for the Linux Base Driver
+  for the Intel PRO/1000 Family of Adapters is e1000.
 
-  As an example, if you install the e1000 driver for two PRO/1000 adapters 
-  (eth0 and eth1) and set the speed and duplex to 10full and 100half, add the 
-  following to modules.conf:
+  As an example, if you install the e1000 driver for two PRO/1000 adapters
+  (eth0 and eth1) and set the speed and duplex to 10full and 100half, add
+  the following to modules.conf or or modprobe.conf:
 
        alias eth0 e1000
        alias eth1 e1000
@@ -297,9 +359,9 @@ Additional Configurations
   Viewing Link Messages
   ---------------------
 
-  Link messages will not be displayed to the console if the distribution is 
-  restricting system messages. In order to see network driver link messages on 
-  your console, set dmesg to eight by entering the following:
+  Link messages will not be displayed to the console if the distribution is
+  restricting system messages. In order to see network driver link messages
+  on your console, set dmesg to eight by entering the following:
 
        dmesg -n 8
 
@@ -308,22 +370,42 @@ Additional Configurations
   Jumbo Frames
   ------------
 
-  The driver supports Jumbo Frames for all adapters except 82542-based 
-  adapters. Jumbo Frames support is enabled by changing the MTU to a value 
-  larger than the default of 1500. Use the ifconfig command to increase the 
-  MTU size. For example:
+  The driver supports Jumbo Frames for all adapters except 82542 and
+  82573-based adapters. Jumbo Frames support is enabled by changing the
+  MTU to a value larger than the default of 1500. Use the ifconfig command
+  to increase the MTU size. For example:
+
+       ifconfig eth<x> mtu 9000 up
+
+  This setting is not saved across reboots.  It can be made permanent if
+  you add:
+
+       MTU=9000
 
-        ifconfig ethx mtu 9000 up
+   to the file /etc/sysconfig/network-scripts/ifcfg-eth<x>.  This example
+   applies to the Red Hat distributions; other distributions may store this
+   setting in a different location.
 
-  The maximum MTU setting for Jumbo Frames is 16110. This value coincides 
-  with the maximum Jumbo Frames size of 16128.
+  Notes:
 
-  NOTE: Jumbo Frames are supported at 1000 Mbps only. Using Jumbo Frames at 
-  10 or 100 Mbps may result in poor performance or loss of link.
+  - To enable Jumbo Frames, increase the MTU size on the interface beyond
+    1500.
+  - The maximum MTU setting for Jumbo Frames is 16110. This value coincides
+    with the maximum Jumbo Frames size of 16128.
+  - Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or
+    loss of link.
+  - Some Intel gigabit adapters that support Jumbo Frames have a frame size
+    limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes.
+    The adapters with this limitation are based on the Intel 82571EB and
+    82572EI controllers, which correspond to these product names:
+     Intel® PRO/1000 PT Dual Port Server Adapter
+     Intel® PRO/1000 PF Dual Port Server Adapter
+     Intel® PRO/1000 PT Server Adapter
+     Intel® PRO/1000 PT Desktop Adapter
+     Intel® PRO/1000 PF Server Adapter
 
+  - The Intel PRO/1000 PM Network Connection does not support jumbo frames.
 
-  NOTE: MTU designates the frame size. To enable Jumbo Frames, increase the
-  MTU size on the interface beyond 1500.
 
   Ethtool
   -------
@@ -333,32 +415,41 @@ Additional Configurations
   version 1.6 or later is required for this functionality.
 
   The latest release of ethtool can be found from
-  http://sf.net/projects/gkernel.  
+  http://sourceforge.net/projects/gkernel.
 
-  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support 
-  for a more complete ethtool feature set can be enabled by upgrading 
-  ethtool to ethtool-1.8.1. 
+  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
+  for a more complete ethtool feature set can be enabled by upgrading
+  ethtool to ethtool-1.8.1.
 
   Enabling Wake on LAN* (WoL)
   ---------------------------
 
   WoL is configured through the Ethtool* utility. Ethtool is included with
-  all versions of Red Hat after Red Hat 7.2. For other Linux distributions, 
-  download and install Ethtool from the following website: 
+  all versions of Red Hat after Red Hat 7.2. For other Linux distributions,
+  download and install Ethtool from the following website:
   http://sourceforge.net/projects/gkernel.
 
-  For instructions on enabling WoL with Ethtool, refer to the website listed 
+  For instructions on enabling WoL with Ethtool, refer to the website listed
   above.
 
-  WoL will be enabled on the system during the next shut down or reboot. 
-  For this driver version, in order to enable WoL, the e1000 driver must be 
+  WoL will be enabled on the system during the next shut down or reboot.
+  For this driver version, in order to enable WoL, the e1000 driver must be
   loaded when shutting down or rebooting the system.
 
   NAPI
   ----
 
   NAPI (Rx polling mode) is supported in the e1000 driver. NAPI is enabled
-  or disabled based on the configuration of the kernel. 
+  or disabled based on the configuration of the kernel. To override
+  the default, use the following compile-time flags.
+
+  To enable NAPI, compile the driver module, passing in a configuration option:
+
+       make CFLAGS_EXTRA=-DE1000_NAPI install
+
+  To disable NAPI, compile the driver module, passing in a configuration option:
+
+       make CFLAGS_EXTRA=-DE1000_NO_NAPI install
 
   See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
 
@@ -369,10 +460,85 @@ Known Issues
   Jumbo Frames System Requirement
   -------------------------------
 
-  Memory allocation failures have been observed on Linux systems with 64 MB 
-  of RAM or less that are running Jumbo Frames. If you are using Jumbo Frames,
-  your system may require more than the advertised minimum requirement of 64 MB
-  of system memory.
+  Memory allocation failures have been observed on Linux systems with 64 MB
+  of RAM or less that are running Jumbo Frames. If you are using Jumbo
+  Frames, your system may require more than the advertised minimum
+  requirement of 64 MB of system memory.
+
+  Performance Degradation with Jumbo Frames
+  -----------------------------------------
+
+  Degradation in throughput performance may be observed in some Jumbo frames
+  environments. If this is observed, increasing the application's socket
+  buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values
+  may help. See the specific application manual and
+  /usr/src/linux*/Documentation/
+  networking/ip-sysctl.txt for more details.
+
+  Jumbo frames on Foundry BigIron 8000 switch
+  -------------------------------------------
+  There is a known issue using Jumbo frames when connected to a Foundry
+  BigIron 8000 switch. This is a 3rd party limitation. If you experience
+  loss of packets, lower the MTU size.
+
+  Multiple Interfaces on Same Ethernet Broadcast Network
+  ------------------------------------------------------
+
+  Due to the default ARP behavior on Linux, it is not possible to have
+  one system on two IP networks in the same Ethernet broadcast domain
+  (non-partitioned switch) behave as expected. All Ethernet interfaces
+  will respond to IP traffic for any IP address assigned to the system.
+  This results in unbalanced receive traffic.
+
+  If you have multiple interfaces in a server, either turn on ARP
+  filtering by entering:
+
+      echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
+  (this only works if your kernel's version is higher than 2.4.5),
+
+  NOTE: This setting is not saved across reboots. The configuration
+  change can be made permanent by adding the line:
+      net.ipv4.conf.all.arp_filter = 1
+  to the file /etc/sysctl.conf
+
+        or,
+
+  install the interfaces in separate broadcast domains (either in
+  different switches or in a switch partitioned to VLANs).
+
+  82541/82547 can't link or are slow to link with some link partners
+  -----------------------------------------------------------------
+
+  There is a known compatibility issue with 82541/82547 and some
+  low-end switches where the link will not be established, or will
+  be slow to establish.  In particular, these switches are known to
+  be incompatible with 82541/82547:
+
+      Planex FXG-08TE
+      I-O Data ETG-SH8
+
+  To workaround this issue, the driver can be compiled with an override
+  of the PHY's master/slave setting.  Forcing master or forcing slave
+  mode will improve time-to-link.
+
+      # make EXTRA_CFLAGS=-DE1000_MASTER_SLAVE=<n>
+
+  Where <n> is:
+
+      0 = Hardware default
+      1 = Master mode
+      2 = Slave mode
+      3 = Auto master/slave
+
+  Disable rx flow control with ethtool
+  ------------------------------------
+
+  In order to disable receive flow control using ethtool, you must turn
+  off auto-negotiation on the same command line.
+
+  For example:
+
+     ethtool -A eth? autoneg off rx off
 
 
 Support
@@ -382,20 +548,24 @@ For general information, go to the Intel support website at:
 
     http://support.intel.com
 
+    or the Intel Wired Networking project hosted by Sourceforge at:
+
+    http://sourceforge.net/projects/e1000
+
 If an issue is identified with the released source code on the supported
-kernel with a supported adapter, email the specific information related to 
-the issue to linux.nics@intel.com.
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sourceforge.net
 
 
 License
 =======
 
-This software program is released under the terms of a license agreement 
-between you ('Licensee') and Intel. Do not use or load this software or any 
-associated materials (collectively, the 'Software') until you have carefully 
-read the full terms and conditions of the LICENSE located in this software 
-package. By loading or using the Software, you agree to the terms of this 
-Agreement. If you do not agree with the terms of this Agreement, do not 
+This software program is released under the terms of a license agreement
+between you ('Licensee') and Intel. Do not use or load this software or any
+associated materials (collectively, the 'Software') until you have carefully
+read the full terms and conditions of the file COPYING located in this software
+package. By loading or using the Software, you agree to the terms of this
+Agreement. If you do not agree with the terms of this Agreement, do not
 install or use the Software.
 
 * Other names and brands may be claimed as the property of others.
index b0dc75a5e74e2c6749fce0f5418fc69eb261a3f7..dd1351dc32b895b5298fabe7c0c37062af9489c4 100644 (file)
@@ -1349,10 +1349,10 @@ S:      Maintained
 INTEL PRO/100 ETHERNET SUPPORT
 P:     John Ronciak
 M:     john.ronciak@intel.com
-P:     Ganesh Venkatesan
-M:     ganesh.venkatesan@intel.com
 P:     Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
+P:     Jeff Kirsher
+M:     jeffrey.t.kirsher@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1361,18 +1361,22 @@ P:      Jeb Cramer
 M:     cramerj@intel.com
 P:     John Ronciak
 M:     john.ronciak@intel.com
-P:     Ganesh Venkatesan
-M:     ganesh.venkatesan@intel.com
+P:     Jesse Brandeburg
+M:     jesse.brandeburg@intel.com
+P:     Jeff Kirsher
+M:     jeffrey.t.kirsher@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
 INTEL PRO/10GbE SUPPORT
+P:     Jeff Kirsher
+M:     jeffrey.t.kirsher@intel.com
 P:     Ayyappan Veeraiyan
 M:     ayyappan.veeraiyan@intel.com
-P:     Ganesh Venkatesan
-M:     ganesh.venkatesan@intel.com
 P:     John Ronciak
 M:     john.ronciak@intel.com
+P:     Jesse Brandeburg
+M:     jesse.brandeburg@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
index 486d7945583d1d59fde2dbff8e2f919f1ef06273..544ac5dc09eb60e2b00eb5ea58e6da483a266030 100644 (file)
@@ -357,7 +357,7 @@ free_reserved_mem(void *start, void *end)
        void *__start = start;
        for (; __start < end; __start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(__start));
-               set_page_count(virt_to_page(__start), 1);
+               init_page_count(virt_to_page(__start));
                free_page((long)__start);
                totalram_pages++;
        }
index c2ee18d2075e7bd22312835cf9c3d859c0913f5b..8a1bfcd500871dde0eb02b72962ef06060ae6b88 100644 (file)
@@ -223,6 +223,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                pte = consistent_pte[idx] + off;
                c->vm_pages = page;
 
+               split_page(page, order);
+
                /*
                 * Set the "dma handle"
                 */
@@ -231,7 +233,6 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                do {
                        BUG_ON(!pte_none(*pte));
 
-                       set_page_count(page, 1);
                        /*
                         * x86 does not mark the pages reserved...
                         */
@@ -250,7 +251,6 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                 * Free the otherwise unused pages.
                 */
                while (page < end) {
-                       set_page_count(page, 1);
                        __free_page(page);
                        page++;
                }
index 8b276ee38acfabdb65b35e6b07903716b9db100d..b0321e943b7693a5e1122e7c2d453218f1efd798 100644 (file)
@@ -531,7 +531,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s)
        for (; addr < end; addr += PAGE_SIZE) {
                struct page *page = virt_to_page(addr);
                ClearPageReserved(page);
-               set_page_count(page, 1);
+               init_page_count(page);
                free_page(addr);
                totalram_pages++;
        }
index 1f09a9d0fb8375297c97f38d2907f3f03793bfaf..e3ecaa4537478d8cb8c9f47f114f9eae76d46228 100644 (file)
@@ -324,7 +324,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s)
        for (; addr < end; addr += PAGE_SIZE) {
                struct page *page = virt_to_page(addr);
                ClearPageReserved(page);
-               set_page_count(page, 1);
+               init_page_count(page);
                free_page(addr);
                totalram_pages++;
        }
index 31a0018b525aa795793c50e25ac58cae1b259371..b7842ff213a6688f3e675e5c39b78bf311a34c12 100644 (file)
@@ -216,7 +216,7 @@ free_initmem(void)
         addr = (unsigned long)(&__init_begin);
         for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                 ClearPageReserved(virt_to_page(addr));
-                set_page_count(virt_to_page(addr), 1);
+                init_page_count(virt_to_page(addr));
                 free_page(addr);
                 totalram_pages++;
         }
index 0f1c6cbc4f50706e50267be0f41b666784afa83e..aa6b7d0a2109388f4be5515c922162f5aa61fc87 100644 (file)
@@ -27,6 +27,7 @@ EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 
 EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
index 342823aad758c13087c0f20c8c06e6ccc3d1dffd..636b2f8b5d981934e2b1a99635ae397d0779d7de 100644 (file)
@@ -115,9 +115,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
         */
        if (order > 0) {
                struct page *rpage = virt_to_page(page);
-
-               for (i = 1; i < (1 << order); i++)
-                       set_page_count(rpage + i, 1);
+               split_page(rpage, order);
        }
 
        err = 0;
index 765088ea8a505844649258d9f2dd7cb60904e047..8899aa1a4f06f6e0d32a8d125b4a3b247ca53025 100644 (file)
@@ -169,7 +169,7 @@ void __init mem_init(void)
                struct page *page = &mem_map[pfn];
 
                ClearPageReserved(page);
-               set_page_count(page, 1);
+               init_page_count(page);
                __free_page(page);
                totalram_pages++;
        }
@@ -210,7 +210,7 @@ void __init free_initmem(void)
        /* next to check that the page we free is not a partial page */
        for (addr = start; addr < end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
@@ -230,7 +230,7 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
        int pages = 0;
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
                pages++;
index 5cc76efaf7aa2838ccd711052732c0a2e8fc6021..69d6ad32d56c86794c70f32687278ff8846bce6d 100644 (file)
@@ -25,6 +25,7 @@ extern char h8300_debug_device[];
 /* platform dependent support */
 
 EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
index 1e0929ddc8c46b6c897cee48668779a1c989895c..09efc4b1f038f5b66ba444bd904660bdac44c319 100644 (file)
@@ -196,7 +196,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        int pages = 0;
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
                pages++;
@@ -219,7 +219,7 @@ free_initmem()
        /* next to check that the page we free is not a partial page */
        for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
index c9cad7ba0d2d5eced0508ff256eb1c1a62c92764..aeabb41968610f3aedce1fbff43fad4e3bbebd35 100644 (file)
@@ -115,7 +115,7 @@ static void efi_call_phys_epilog(void)
        unsigned long cr4;
        struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
 
-       cpu_gdt_descr->address = __va(cpu_gdt_descr->address);
+       cpu_gdt_descr->address = (unsigned long)__va(cpu_gdt_descr->address);
        load_gdt(cpu_gdt_descr);
 
        cr4 = read_cr4();
index 218d725a5a1e89ff7f3dc7175ca22c59624e7b96..d134e9643a58a0303cb67672486709d9da244591 100644 (file)
@@ -504,27 +504,23 @@ void unlock_ipi_call_lock(void)
        spin_unlock_irq(&call_lock);
 }
 
-static struct call_data_struct * call_data;
-
-/*
- * this function sends a 'generic call function' IPI to all other CPUs
- * in the system.
- */
-
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-                       int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
+static struct call_data_struct *call_data;
+
+/**
+ * smp_call_function(): Run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: currently unused.
+ * @wait: If true, wait (atomically) until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code. Does not return until
  * remote CPUs are nearly ready to execute <<func>> or are or have executed.
  *
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler or from a bottom half handler.
  */
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+                       int wait)
 {
        struct call_data_struct data;
        int cpus;
index a4a61976ecb922fea01df1a5ea4d07dbc3f155bf..8fdb1fb17a5f0ca457cdf0bdaa8e3d998fcd0ccf 100644 (file)
@@ -40,14 +40,13 @@ asmlinkage int sys_pipe(unsigned long __user * fildes)
        return error;
 }
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-       unsigned long addr, unsigned long len,
-       unsigned long prot, unsigned long flags,
-       unsigned long fd, unsigned long pgoff)
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+                         unsigned long prot, unsigned long flags,
+                         unsigned long fd, unsigned long pgoff)
 {
        int error = -EBADF;
-       struct file * file = NULL;
+       struct file *file = NULL;
+       struct mm_struct *mm = current->mm;
 
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
        if (!(flags & MAP_ANONYMOUS)) {
@@ -56,9 +55,9 @@ static inline long do_mmap2(
                        goto out;
        }
 
-       down_write(&current->mm->mmap_sem);
+       down_write(&mm->mmap_sem);
        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-       up_write(&current->mm->mmap_sem);
+       up_write(&mm->mmap_sem);
 
        if (file)
                fput(file);
@@ -66,13 +65,6 @@ out:
        return error;
 }
 
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-       unsigned long prot, unsigned long flags,
-       unsigned long fd, unsigned long pgoff)
-{
-       return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls. Linux/i386 didn't use to be able to handle more than
@@ -101,7 +93,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
        if (a.offset & ~PAGE_MASK)
                goto out;
 
-       err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+       err = sys_mmap2(a.addr, a.len, a.prot, a.flags,
+                       a.fd, a.offset >> PAGE_SHIFT);
 out:
        return err;
 }
index be242723c33988fc2cf8222ea20430554e775c89..17a6fe7166e7b48c2a2956a440918131e470f712 100644 (file)
@@ -46,7 +46,7 @@ static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
  *
  *                     -johnstul@us.ibm.com "math is hard, lets go shopping!"
  */
-static unsigned long cyc2ns_scale;
+static unsigned long cyc2ns_scale __read_mostly;
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
 static inline void set_cyc2ns_scale(unsigned long cpu_khz)
index a7f5a2aceba2d335402a48168d749f2736dadf41..5e41ee29c8cff1dff22ffd7142b7dfc96f9e3594 100644 (file)
@@ -74,7 +74,7 @@ late_initcall(start_lost_tick_compensation);
  *
  *                     -johnstul@us.ibm.com "math is hard, lets go shopping!"
  */
-static unsigned long cyc2ns_scale
+static unsigned long cyc2ns_scale __read_mostly;
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
 static inline void set_cyc2ns_scale(unsigned long cpu_khz)
index d524127c9afc3b2f92b3e5ad6b3dbce20bec42f7..a7d8915854116264048f62c84d63dc495fc212b7 100644 (file)
@@ -48,18 +48,6 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        return (pte_t *) pmd;
 }
 
-/*
- * This function checks for proper alignment of input addr and len parameters.
- */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
-{
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-       return 0;
-}
-
 #if 0  /* This is just for testing */
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
index 2700f01994ba1645ff788bc0310898492ac86ede..7ba55a6e2dbcd3e51dadce36e32a7a33260ddaad 100644 (file)
@@ -270,7 +270,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
 
 static void __meminit free_new_highpage(struct page *page)
 {
-       set_page_count(page, 1);
+       init_page_count(page);
        __free_page(page);
        totalhigh_pages++;
 }
@@ -727,7 +727,7 @@ void free_initmem(void)
        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                memset((void *)addr, 0xcc, PAGE_SIZE);
                free_page(addr);
                totalram_pages++;
@@ -766,7 +766,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
index d0cadb33b54c1088f4eb609a28409fecf7ed7c74..92c3d9f0e7314f984fdd60a3ffbbfd3b01259edc 100644 (file)
@@ -51,6 +51,13 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
        if (!base) 
                return NULL;
 
+       /*
+        * page_private is used to track the number of entries in
+        * the page table page that have non standard attributes.
+        */
+       SetPagePrivate(base);
+       page_private(base) = 0;
+
        address = __pa(address);
        addr = address & LARGE_PAGE_MASK; 
        pbase = (pte_t *)page_address(base);
@@ -143,11 +150,12 @@ __change_page_attr(struct page *page, pgprot_t prot)
                                return -ENOMEM;
                        set_pmd_pte(kpte,address,mk_pte(split, ref_prot));
                        kpte_page = split;
-               }       
-               get_page(kpte_page);
+               }
+               page_private(kpte_page)++;
        } else if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
                set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL));
-               __put_page(kpte_page);
+               BUG_ON(page_private(kpte_page) == 0);
+               page_private(kpte_page)--;
        } else
                BUG();
 
@@ -157,10 +165,8 @@ __change_page_attr(struct page *page, pgprot_t prot)
         * replace it with a largepage.
         */
        if (!PageReserved(kpte_page)) {
-               /* memleak and potential failed 2M page regeneration */
-               BUG_ON(!page_count(kpte_page));
-
-               if (cpu_has_pse && (page_count(kpte_page) == 1)) {
+               if (cpu_has_pse && (page_private(kpte_page) == 0)) {
+                       ClearPagePrivate(kpte_page);
                        list_add(&kpte_page->lru, &df_list);
                        revert_page(kpte_page, address);
                }
index a85ea9d37f056de90e4eaecf5124404ef51ce767..ff7ae6b664e8af12509a0f5d19f0231ce34dd14d 100644 (file)
@@ -271,6 +271,25 @@ config SCHED_SMT
          Intel IA64 chips with MultiThreading at a cost of slightly increased
          overhead in some places. If unsure say N here.
 
+config PERMIT_BSP_REMOVE
+       bool "Support removal of Bootstrap Processor"
+       depends on HOTPLUG_CPU
+       default n
+       ---help---
+       Say Y here if your platform SAL will support removal of BSP with HOTPLUG_CPU
+       support. 
+
+config FORCE_CPEI_RETARGET
+       bool "Force assumption that CPEI can be re-targetted"
+       depends on PERMIT_BSP_REMOVE
+       default n
+       ---help---
+       Say Y if you need to force the assumption that CPEI can be re-targetted to
+       any cpu in the system. This hint is available via ACPI 3.0 specifications.
+       Tiger4 systems are capable of re-directing CPEI to any CPU other than BSP.
+       This option it useful to enable this feature on older BIOS's as well.
+       You can also enable this by using boot command line option force_cpei=1.
+
 config PREEMPT
        bool "Preemptible Kernel"
         help
index 125568118b847b97dbe217c5367d1a1871444699..766bf495543249e44bfd69d92a31ebd3a69b47cc 100644 (file)
@@ -116,6 +116,8 @@ CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_HOTPLUG_CPU=y
+CONFIG_PERMIT_BSP_REMOVE=y
+CONFIG_FORCE_CPEI_RETARGET=y
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_SELECT_MEMORY_MODEL=y
index ecd44bdc8394fee371fc944af433163d0adb3952..4722ec51c70c6583ca38729f181d3779ad2e5146 100644 (file)
@@ -284,19 +284,24 @@ acpi_parse_plat_int_src(acpi_table_entry_header * header,
        return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 unsigned int can_cpei_retarget(void)
 {
        extern int cpe_vector;
+       extern unsigned int force_cpei_retarget;
 
        /*
         * Only if CPEI is supported and the override flag
         * is present, otherwise return that its re-targettable
         * if we are in polling mode.
         */
-       if (cpe_vector > 0 && !acpi_cpei_override)
-               return 0;
-       else
-               return 1;
+       if (cpe_vector > 0) {
+               if (acpi_cpei_override || force_cpei_retarget)
+                       return 1;
+               else
+                       return 0;
+       }
+       return 1;
 }
 
 unsigned int is_cpu_cpei_target(unsigned int cpu)
@@ -315,6 +320,7 @@ void set_cpei_target_cpu(unsigned int cpu)
 {
        acpi_cpei_phys_cpuid = cpu_physical_id(cpu);
 }
+#endif
 
 unsigned int get_cpei_target_cpu(void)
 {
index 930fdfca6ddb610092a92f692419469fe4cab39d..0e3eda99e5494eb21187894dae2556717d37f6f0 100644 (file)
@@ -1102,9 +1102,6 @@ skip_rbs_switch:
        st8 [r2]=r8
        st8 [r3]=r10
 .work_pending:
-       tbit.nz p6,p0=r31,TIF_SIGDELAYED                // signal delayed from  MCA/INIT/NMI/PMI context?
-(p6)   br.cond.sptk.few .sigdelayed
-       ;;
        tbit.z p6,p0=r31,TIF_NEED_RESCHED               // current_thread_info()->need_resched==0?
 (p6)   br.cond.sptk.few .notify
 #ifdef CONFIG_PREEMPT
@@ -1131,17 +1128,6 @@ skip_rbs_switch:
 (pLvSys)br.cond.sptk.few  .work_pending_syscall_end
        br.cond.sptk.many .work_processed_kernel        // don't re-check
 
-// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where
-// it could not be delivered.  Deliver it now.  The signal might be for us and
-// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed
-// signal.
-
-.sigdelayed:
-       br.call.sptk.many rp=do_sigdelayed
-       cmp.eq p6,p0=r0,r0                              // p6 <- 1, always re-check
-(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
-       br.cond.sptk.many .work_processed_kernel        // re-check
-
 .work_pending_syscall_end:
        adds r2=PT(R8)+16,r12
        adds r3=PT(R10)+16,r12
index 574084f343fad79b32406c6e8b354c23554594bf..8832c553230ae1681e051858afd6912cb6a289f7 100644 (file)
@@ -631,6 +631,7 @@ get_target_cpu (unsigned int gsi, int vector)
 {
 #ifdef CONFIG_SMP
        static int cpu = -1;
+       extern int cpe_vector;
 
        /*
         * In case of vector shared by multiple RTEs, all RTEs that
@@ -653,6 +654,11 @@ get_target_cpu (unsigned int gsi, int vector)
        if (!cpu_online(smp_processor_id()))
                return cpu_physical_id(smp_processor_id());
 
+#ifdef CONFIG_ACPI
+       if (cpe_vector > 0 && vector == IA64_CPEP_VECTOR)
+               return get_cpei_target_cpu();
+#endif
+
 #ifdef CONFIG_NUMA
        {
                int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
index d33244c3275914f8ecdfeb769c1a9aad92710eff..5ce908ef9c9585f5f0350503fa39caf0e3e732bf 100644 (file)
@@ -163,8 +163,19 @@ void fixup_irqs(void)
 {
        unsigned int irq;
        extern void ia64_process_pending_intr(void);
+       extern void ia64_disable_timer(void);
+       extern volatile int time_keeper_id;
+
+       ia64_disable_timer();
+
+       /*
+        * Find a new timesync master
+        */
+       if (smp_processor_id() == time_keeper_id) {
+               time_keeper_id = first_cpu(cpu_online_map);
+               printk ("CPU %d is now promoted to time-keeper master\n", time_keeper_id);
+       }
 
-       ia64_set_itv(1<<16);
        /*
         * Phase 1: Locate irq's bound to this cpu and
         * relocate them for cpu removal.
index ee7eec9ee57648cee03a84aeacea97651577131d..b57e723f194c782aa6bc639717dcd57d5db0a947 100644 (file)
@@ -281,14 +281,10 @@ ia64_mca_log_sal_error_record(int sal_info_type)
                ia64_sal_clear_state_info(sal_info_type);
 }
 
-/*
- * platform dependent error handling
- */
-#ifndef PLATFORM_MCA_HANDLERS
-
 #ifdef CONFIG_ACPI
 
 int cpe_vector = -1;
+int ia64_cpe_irq = -1;
 
 static irqreturn_t
 ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
@@ -377,8 +373,6 @@ ia64_mca_register_cpev (int cpev)
 }
 #endif /* CONFIG_ACPI */
 
-#endif /* PLATFORM_MCA_HANDLERS */
-
 /*
  * ia64_mca_cmc_vector_setup
  *
@@ -630,6 +624,32 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
        *tnat |= (nat << tslot);
 }
 
+/* Change the comm field on the MCA/INT task to include the pid that
+ * was interrupted, it makes for easier debugging.  If that pid was 0
+ * (swapper or nested MCA/INIT) then use the start of the previous comm
+ * field suffixed with its cpu.
+ */
+
+static void
+ia64_mca_modify_comm(const task_t *previous_current)
+{
+       char *p, comm[sizeof(current->comm)];
+       if (previous_current->pid)
+               snprintf(comm, sizeof(comm), "%s %d",
+                       current->comm, previous_current->pid);
+       else {
+               int l;
+               if ((p = strchr(previous_current->comm, ' ')))
+                       l = p - previous_current->comm;
+               else
+                       l = strlen(previous_current->comm);
+               snprintf(comm, sizeof(comm), "%s %*s %d",
+                       current->comm, l, previous_current->comm,
+                       task_thread_info(previous_current)->cpu);
+       }
+       memcpy(current->comm, comm, sizeof(current->comm));
+}
+
 /* On entry to this routine, we are running on the per cpu stack, see
  * mca_asm.h.  The original stack has not been touched by this event.  Some of
  * the original stack's registers will be in the RBS on this stack.  This stack
@@ -648,7 +668,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
                struct ia64_sal_os_state *sos,
                const char *type)
 {
-       char *p, comm[sizeof(current->comm)];
+       char *p;
        ia64_va va;
        extern char ia64_leave_kernel[];        /* Need asm address, not function descriptor */
        const pal_min_state_area_t *ms = sos->pal_min_state;
@@ -721,6 +741,10 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
        /* Verify the previous stack state before we change it */
        if (user_mode(regs)) {
                msg = "occurred in user space";
+               /* previous_current is guaranteed to be valid when the task was
+                * in user space, so ...
+                */
+               ia64_mca_modify_comm(previous_current);
                goto no_mod;
        }
        if (r13 != sos->prev_IA64_KR_CURRENT) {
@@ -750,25 +774,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
                goto no_mod;
        }
 
-       /* Change the comm field on the MCA/INT task to include the pid that
-        * was interrupted, it makes for easier debugging.  If that pid was 0
-        * (swapper or nested MCA/INIT) then use the start of the previous comm
-        * field suffixed with its cpu.
-        */
-       if (previous_current->pid)
-               snprintf(comm, sizeof(comm), "%s %d",
-                       current->comm, previous_current->pid);
-       else {
-               int l;
-               if ((p = strchr(previous_current->comm, ' ')))
-                       l = p - previous_current->comm;
-               else
-                       l = strlen(previous_current->comm);
-               snprintf(comm, sizeof(comm), "%s %*s %d",
-                       current->comm, l, previous_current->comm,
-                       task_thread_info(previous_current)->cpu);
-       }
-       memcpy(current->comm, comm, sizeof(current->comm));
+       ia64_mca_modify_comm(previous_current);
 
        /* Make the original task look blocked.  First stack a struct pt_regs,
         * describing the state at the time of interrupt.  mca_asm.S built a
@@ -908,7 +914,7 @@ no_mod:
 static void
 ia64_wait_for_slaves(int monarch)
 {
-       int c, wait = 0;
+       int c, wait = 0, missing = 0;
        for_each_online_cpu(c) {
                if (c == monarch)
                        continue;
@@ -919,15 +925,32 @@ ia64_wait_for_slaves(int monarch)
                }
        }
        if (!wait)
-               return;
+               goto all_in;
        for_each_online_cpu(c) {
                if (c == monarch)
                        continue;
                if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
                        udelay(5*1000000);      /* wait 5 seconds for slaves (arbitrary) */
+                       if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
+                               missing = 1;
                        break;
                }
        }
+       if (!missing)
+               goto all_in;
+       printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
+       for_each_online_cpu(c) {
+               if (c == monarch)
+                       continue;
+               if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
+                       printk(" %d", c);
+       }
+       printk("\n");
+       return;
+
+all_in:
+       printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
+       return;
 }
 
 /*
@@ -953,6 +976,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        task_t *previous_current;
 
        oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
+       console_loglevel = 15;  /* make sure printks make it to console */
+       printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
+               sos->proc_state_param, cpu, sos->monarch);
+
        previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
        monarch_cpu = cpu;
        if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
@@ -1444,11 +1471,13 @@ void __devinit
 ia64_mca_cpu_init(void *cpu_data)
 {
        void *pal_vaddr;
+       static int first_time = 1;
 
-       if (smp_processor_id() == 0) {
+       if (first_time) {
                void *mca_data;
                int cpu;
 
+               first_time = 0;
                mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu)
                                         * NR_CPUS + KERNEL_STACK_SIZE);
                mca_data = (void *)(((unsigned long)mca_data +
@@ -1704,6 +1733,7 @@ ia64_mca_late_init(void)
                                        desc = irq_descp(irq);
                                        desc->status |= IRQ_PER_CPU;
                                        setup_irq(irq, &mca_cpe_irqaction);
+                                       ia64_cpe_irq = irq;
                                }
                        ia64_mca_register_cpev(cpe_vector);
                        IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n", __FUNCTION__);
index 9c5194b385dab33ce122152ee665306fe2cbf761..077f21216b654cc433cb58c2104b11c7954b8b19 100644 (file)
@@ -6722,6 +6722,7 @@ __initcall(pfm_init);
 void
 pfm_init_percpu (void)
 {
+       static int first_time=1;
        /*
         * make sure no measurement is active
         * (may inherit programmed PMCs from EFI).
@@ -6734,8 +6735,10 @@ pfm_init_percpu (void)
         */
        pfm_unfreeze_pmu();
 
-       if (smp_processor_id() == 0)
+       if (first_time) {
                register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
+               first_time=0;
+       }
 
        ia64_setreg(_IA64_REG_CR_PMV, IA64_PERFMON_VECTOR);
        ia64_srlz_d();
index 463f6bb44d07880993b0f13e282352100dd05cff..1d7903ee2126ec08183aa569bb4d8d8ef8f472dc 100644 (file)
@@ -588,104 +588,3 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
        }
        return 0;
 }
-
-/* Set a delayed signal that was detected in MCA/INIT/NMI/PMI context where it
- * could not be delivered.  It is important that the target process is not
- * allowed to do any more work in user space.  Possible cases for the target
- * process:
- *
- * - It is sleeping and will wake up soon.  Store the data in the current task,
- *   the signal will be sent when the current task returns from the next
- *   interrupt.
- *
- * - It is running in user context.  Store the data in the current task, the
- *   signal will be sent when the current task returns from the next interrupt.
- *
- * - It is running in kernel context on this or another cpu and will return to
- *   user context.  Store the data in the target task, the signal will be sent
- *   to itself when the target task returns to user space.
- *
- * - It is running in kernel context on this cpu and will sleep before
- *   returning to user context.  Because this is also the current task, the
- *   signal will not get delivered and the task could sleep indefinitely.
- *   Store the data in the idle task for this cpu, the signal will be sent
- *   after the idle task processes its next interrupt.
- *
- * To cover all cases, store the data in the target task, the current task and
- * the idle task on this cpu.  Whatever happens, the signal will be delivered
- * to the target task before it can do any useful user space work.  Multiple
- * deliveries have no unwanted side effects.
- *
- * Note: This code is executed in MCA/INIT/NMI/PMI context, with interrupts
- * disabled.  It must not take any locks nor use kernel structures or services
- * that require locks.
- */
-
-/* To ensure that we get the right pid, check its start time.  To avoid extra
- * include files in thread_info.h, convert the task start_time to unsigned long,
- * giving us a cycle time of > 580 years.
- */
-static inline unsigned long
-start_time_ul(const struct task_struct *t)
-{
-       return t->start_time.tv_sec * NSEC_PER_SEC + t->start_time.tv_nsec;
-}
-
-void
-set_sigdelayed(pid_t pid, int signo, int code, void __user *addr)
-{
-       struct task_struct *t;
-       unsigned long start_time =  0;
-       int i;
-
-       for (i = 1; i <= 3; ++i) {
-               switch (i) {
-               case 1:
-                       t = find_task_by_pid(pid);
-                       if (t)
-                               start_time = start_time_ul(t);
-                       break;
-               case 2:
-                       t = current;
-                       break;
-               default:
-                       t = idle_task(smp_processor_id());
-                       break;
-               }
-
-               if (!t)
-                       return;
-               task_thread_info(t)->sigdelayed.signo = signo;
-               task_thread_info(t)->sigdelayed.code = code;
-               task_thread_info(t)->sigdelayed.addr = addr;
-               task_thread_info(t)->sigdelayed.start_time = start_time;
-               task_thread_info(t)->sigdelayed.pid = pid;
-               wmb();
-               set_tsk_thread_flag(t, TIF_SIGDELAYED);
-       }
-}
-
-/* Called from entry.S when it detects TIF_SIGDELAYED, a delayed signal that
- * was detected in MCA/INIT/NMI/PMI context where it could not be delivered.
- */
-
-void
-do_sigdelayed(void)
-{
-       struct siginfo siginfo;
-       pid_t pid;
-       struct task_struct *t;
-
-       clear_thread_flag(TIF_SIGDELAYED);
-       memset(&siginfo, 0, sizeof(siginfo));
-       siginfo.si_signo = current_thread_info()->sigdelayed.signo;
-       siginfo.si_code = current_thread_info()->sigdelayed.code;
-       siginfo.si_addr = current_thread_info()->sigdelayed.addr;
-       pid = current_thread_info()->sigdelayed.pid;
-       t = find_task_by_pid(pid);
-       if (!t)
-               return;
-       if (current_thread_info()->sigdelayed.start_time != start_time_ul(t))
-               return;
-       force_sig_info(siginfo.si_signo, &siginfo, t);
-}
index b681ef34a86e13a5ecab3a7e1ec2eb6b7378e847..c4b633b36daba12b16b9ebe650b54f009c349fd9 100644 (file)
 #endif
 
 #ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_PERMIT_BSP_REMOVE
+#define bsp_remove_ok  1
+#else
+#define bsp_remove_ok  0
+#endif
+
 /*
  * Store all idle threads, this can be reused instead of creating
  * a new thread. Also avoids complicated thread destroy functionality
@@ -104,7 +110,7 @@ struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
 /*
  * ITC synchronization related stuff:
  */
-#define MASTER 0
+#define MASTER (0)
 #define SLAVE  (SMP_CACHE_BYTES/8)
 
 #define NUM_ROUNDS     64      /* magic value */
@@ -151,6 +157,27 @@ char __initdata no_int_routing;
 
 unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */
 
+#ifdef CONFIG_FORCE_CPEI_RETARGET
+#define CPEI_OVERRIDE_DEFAULT  (1)
+#else
+#define CPEI_OVERRIDE_DEFAULT  (0)
+#endif
+
+unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT;
+
+static int __init
+cmdl_force_cpei(char *str)
+{
+       int value=0;
+
+       get_option (&str, &value);
+       force_cpei_retarget = value;
+
+       return 1;
+}
+
+__setup("force_cpei=", cmdl_force_cpei);
+
 static int __init
 nointroute (char *str)
 {
@@ -161,6 +188,27 @@ nointroute (char *str)
 
 __setup("nointroute", nointroute);
 
+static void fix_b0_for_bsp(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       int cpuid;
+       static int fix_bsp_b0 = 1;
+
+       cpuid = smp_processor_id();
+
+       /*
+        * Cache the b0 value on the first AP that comes up
+        */
+       if (!(fix_bsp_b0 && cpuid))
+               return;
+
+       sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0];
+       printk ("Fixed BSP b0 value from CPU %d\n", cpuid);
+
+       fix_bsp_b0 = 0;
+#endif
+}
+
 void
 sync_master (void *arg)
 {
@@ -327,8 +375,9 @@ smp_setup_percpu_timer (void)
 static void __devinit
 smp_callin (void)
 {
-       int cpuid, phys_id;
+       int cpuid, phys_id, itc_master;
        extern void ia64_init_itm(void);
+       extern volatile int time_keeper_id;
 
 #ifdef CONFIG_PERFMON
        extern void pfm_init_percpu(void);
@@ -336,6 +385,7 @@ smp_callin (void)
 
        cpuid = smp_processor_id();
        phys_id = hard_smp_processor_id();
+       itc_master = time_keeper_id;
 
        if (cpu_online(cpuid)) {
                printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
@@ -343,6 +393,8 @@ smp_callin (void)
                BUG();
        }
 
+       fix_b0_for_bsp();
+
        lock_ipi_calllock();
        cpu_set(cpuid, cpu_online_map);
        unlock_ipi_calllock();
@@ -365,8 +417,8 @@ smp_callin (void)
                 * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls
                 * local_bh_enable(), which bugs out if irqs are not enabled...
                 */
-               Dprintk("Going to syncup ITC with BP.\n");
-               ia64_sync_itc(0);
+               Dprintk("Going to syncup ITC with ITC Master.\n");
+               ia64_sync_itc(itc_master);
        }
 
        /*
@@ -635,6 +687,47 @@ remove_siblinginfo(int cpu)
 }
 
 extern void fixup_irqs(void);
+
+int migrate_platform_irqs(unsigned int cpu)
+{
+       int new_cpei_cpu;
+       irq_desc_t *desc = NULL;
+       cpumask_t       mask;
+       int             retval = 0;
+
+       /*
+        * dont permit CPEI target to removed.
+        */
+       if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) {
+               printk ("CPU (%d) is CPEI Target\n", cpu);
+               if (can_cpei_retarget()) {
+                       /*
+                        * Now re-target the CPEI to a different processor
+                        */
+                       new_cpei_cpu = any_online_cpu(cpu_online_map);
+                       mask = cpumask_of_cpu(new_cpei_cpu);
+                       set_cpei_target_cpu(new_cpei_cpu);
+                       desc = irq_descp(ia64_cpe_irq);
+                       /*
+                        * Switch for now, immediatly, we need to do fake intr
+                        * as other interrupts, but need to study CPEI behaviour with
+                        * polling before making changes.
+                        */
+                       if (desc) {
+                               desc->handler->disable(ia64_cpe_irq);
+                               desc->handler->set_affinity(ia64_cpe_irq, mask);
+                               desc->handler->enable(ia64_cpe_irq);
+                               printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu);
+                       }
+               }
+               if (!desc) {
+                       printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu);
+                       retval = -EBUSY;
+               }
+       }
+       return retval;
+}
+
 /* must be called with cpucontrol mutex held */
 int __cpu_disable(void)
 {
@@ -643,8 +736,17 @@ int __cpu_disable(void)
        /*
         * dont permit boot processor for now
         */
-       if (cpu == 0)
-               return -EBUSY;
+       if (cpu == 0 && !bsp_remove_ok) {
+               printk ("Your platform does not support removal of BSP\n");
+               return (-EBUSY);
+       }
+
+       cpu_clear(cpu, cpu_online_map);
+
+       if (migrate_platform_irqs(cpu)) {
+               cpu_set(cpu, cpu_online_map);
+               return (-EBUSY);
+       }
 
        remove_siblinginfo(cpu);
        cpu_clear(cpu, cpu_online_map);
index 307d01e15b2ea359c043d11c5e19a0bc57bd1002..ac167436e9364ffc23fe3bde276019e5fae93d7e 100644 (file)
@@ -32,7 +32,7 @@
 
 extern unsigned long wall_jiffies;
 
-#define TIME_KEEPER_ID 0       /* smp_processor_id() of time-keeper */
+volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */
 
 #ifdef CONFIG_IA64_DEBUG_IRQ
 
@@ -71,7 +71,7 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 
                new_itm += local_cpu_data->itm_delta;
 
-               if (smp_processor_id() == TIME_KEEPER_ID) {
+               if (smp_processor_id() == time_keeper_id) {
                        /*
                         * Here we are in the timer irq handler. We have irqs locally
                         * disabled, but we don't know if the timer_bh is running on
@@ -236,6 +236,11 @@ static struct irqaction timer_irqaction = {
        .name =         "timer"
 };
 
+void __devinit ia64_disable_timer(void)
+{
+       ia64_set_itv(1 << 16);
+}
+
 void __init
 time_init (void)
 {
index 6e5eea19fa672bb0199f997e0888fc91d98ad77c..3b6fd798c4d68c2a1cbbed752e875286b1d3ff85 100644 (file)
@@ -36,7 +36,7 @@ int arch_register_cpu(int num)
        parent = &sysfs_nodes[cpu_to_node(num)];
 #endif /* CONFIG_NUMA */
 
-#ifdef CONFIG_ACPI
+#if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
        /*
         * If CPEI cannot be re-targetted, and this is
         * CPEI target, then dont create the control file
index acaaec4e46811bdf697fdd96bbd37ac9a41dd6b5..9855ba3180944b2d13569dba7e6f7139dcb0e621 100644 (file)
@@ -181,13 +181,15 @@ per_cpu_init (void)
 {
        void *cpu_data;
        int cpu;
+       static int first_time=1;
 
        /*
         * get_free_pages() cannot be used before cpu_init() done.  BSP
         * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls
         * get_zeroed_page().
         */
-       if (smp_processor_id() == 0) {
+       if (first_time) {
+               first_time=0;
                cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
                                           PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
                for (cpu = 0; cpu < NR_CPUS; cpu++) {
index c87d6d1d58130411828e2daef886398ced41d93d..573d5cc63e2b927eaf0791833018b8643172d64d 100644 (file)
@@ -528,12 +528,17 @@ void __init find_memory(void)
 void *per_cpu_init(void)
 {
        int cpu;
+       static int first_time = 1;
+
 
        if (smp_processor_id() != 0)
                return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
-               per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+       if (first_time) {
+               first_time = 0;
+               for (cpu = 0; cpu < NR_CPUS; cpu++)
+                       per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+       }
 
        return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 }
index 2d13889d0a9915da645b074ecbef1f8a0b56d116..9dbc7dadd1653a79b078fa1b79f1e43266db84db 100644 (file)
@@ -68,9 +68,10 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr)
 #define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
 
 /*
- * This function checks for proper alignment of input addr and len parameters.
+ * Don't actually need to do any preparation, but need to make sure
+ * the address is in the right region.
  */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+int prepare_hugepage_range(unsigned long addr, unsigned long len)
 {
        if (len & ~HPAGE_MASK)
                return -EINVAL;
index b38b6d213c158ad0651a20a343e4a3f8327d7f98..08d94e6bfa18bcd2bc823231e3a73944927bf041 100644 (file)
@@ -197,7 +197,7 @@ free_initmem (void)
        eaddr = (unsigned long) ia64_imva(__init_end);
        while (addr < eaddr) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                ++totalram_pages;
                addr += PAGE_SIZE;
@@ -252,7 +252,7 @@ free_initrd_mem (unsigned long start, unsigned long end)
                        continue;
                page = virt_to_page(start);
                ClearPageReserved(page);
-               set_page_count(page, 1);
+               init_page_count(page);
                free_page(start);
                ++totalram_pages;
        }
@@ -640,7 +640,7 @@ mem_init (void)
 void online_page(struct page *page)
 {
        ClearPageReserved(page);
-       set_page_count(page, 1);
+       init_page_count(page);
        __free_page(page);
        totalram_pages++;
        num_physpages++;
index 3e9b4eea74185a32d3ea235d040213936996848f..ab9c48c88012916a28deb08d1bcf7749b1ec02af 100644 (file)
@@ -10,7 +10,8 @@
 CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
 
 obj-y                          += setup.o bte.o bte_error.o irq.o mca.o idle.o \
-                                  huberror.o io_init.o iomv.o klconflib.o sn2/
+                                  huberror.o io_init.o iomv.o klconflib.o pio_phys.o \
+                                  sn2/
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
 obj-$(CONFIG_SGI_TIOCX)                += tiocx.o
 obj-$(CONFIG_IA64_SGI_SN_XP)   += xp.o
diff --git a/arch/ia64/sn/kernel/pio_phys.S b/arch/ia64/sn/kernel/pio_phys.S
new file mode 100644 (file)
index 0000000..3c7d48d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This file contains macros used to access MMR registers via
+ * uncached physical addresses.
+ *      pio_phys_read_mmr  - read an MMR
+ *      pio_phys_write_mmr - write an MMR
+ *      pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
+ *              Second MMR will be skipped if address is NULL
+ *
+ * Addresses passed to these routines should be uncached physical addresses
+ *     ie., 0x80000....
+ */
+
+
+
+#include <asm/asmmacro.h>
+#include <asm/page.h>
+
+GLOBAL_ENTRY(pio_phys_read_mmr)
+       .prologue
+       .regstk 1,0,0,0
+       .body
+       mov r2=psr
+       rsm psr.i | psr.dt
+       ;;
+       srlz.d
+       ld8.acq r8=[r32]
+       ;;
+       mov psr.l=r2;;
+       srlz.d
+       br.ret.sptk.many rp
+END(pio_phys_read_mmr)
+
+GLOBAL_ENTRY(pio_phys_write_mmr)
+       .prologue
+       .regstk 2,0,0,0
+       .body
+       mov r2=psr
+       rsm psr.i | psr.dt
+       ;;
+       srlz.d
+       st8.rel [r32]=r33
+       ;;
+       mov psr.l=r2;;
+       srlz.d
+       br.ret.sptk.many rp
+END(pio_phys_write_mmr)
+
+GLOBAL_ENTRY(pio_atomic_phys_write_mmrs)
+       .prologue
+       .regstk 4,0,0,0
+       .body
+       mov r2=psr
+       cmp.ne p9,p0=r34,r0;
+       rsm psr.i | psr.dt | psr.ic
+       ;;
+       srlz.d
+       st8.rel [r32]=r33
+(p9)   st8.rel [r34]=r35
+       ;;
+       mov psr.l=r2;;
+       srlz.d
+       br.ret.sptk.many rp
+END(pio_atomic_phys_write_mmrs)
+
+
index 5b84836c2171b1a53c3dddc0cc060055c1433a15..8b6d5c8447089d8523ed807583c9c317cc9caf0b 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/config.h>
@@ -498,6 +498,7 @@ void __init sn_setup(char **cmdline_p)
         * for sn.
         */
        pm_power_off = ia64_sn_power_down;
+       current->thread.flags |= IA64_THREAD_MIGRATION;
 }
 
 /**
@@ -660,7 +661,8 @@ void __init sn_cpu_init(void)
                        SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
                u64 *pio;
                pio = is_shub1() ? pio1 : pio2;
-               pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]);
+               pda->pio_write_status_addr =
+                  (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
                pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
        }
 
index b2e1e746b47fca6ebbda649e50077ce56127c2f2..d9d306c79f2d7a1743369380e637c4118d012c22 100644 (file)
@@ -93,6 +93,27 @@ static inline unsigned long wait_piowc(void)
        return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
 }
 
+/**
+ * sn_migrate - SN-specific task migration actions
+ * @task: Task being migrated to new CPU
+ *
+ * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order.
+ * Context switching user threads which have memory-mapped MMIO may cause
+ * PIOs to issue from seperate CPUs, thus the PIO writes must be drained
+ * from the previous CPU's Shub before execution resumes on the new CPU.
+ */
+void sn_migrate(struct task_struct *task)
+{
+       pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu);
+       volatile unsigned long *adr = last_pda->pio_write_status_addr;
+       unsigned long val = last_pda->pio_write_status_val;
+
+       /* Drain PIO writes from old CPU's Shub */
+       while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK)
+                       != val))
+               cpu_relax();
+}
+
 void sn_tlb_migrate_finish(struct mm_struct *mm)
 {
        /* flush_tlb_mm is inefficient if more than 1 users of mm */
index cdf6856ce089c07c4344f6150439e1bd4ef29523..d0abddd9ffe682c8dc4d566c6619a33b180567a7 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/xpc.h>
 
 
+/*
+ * Guarantee that the kzalloc'd memory is cacheline aligned.
+ */
+static void *
+xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+{
+       /* see if kzalloc will give us cachline aligned memory by default */
+       *base = kzalloc(size, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+               return *base;
+       }
+       kfree(*base);
+
+       /* nope, we'll have to do it ourselves */
+       *base = kzalloc(size + L1_CACHE_BYTES, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       return (void *) L1_CACHE_ALIGN((u64) *base);
+}
+
+
 /*
  * Set up the initial values for the XPartition Communication channels.
  */
@@ -93,20 +117,19 @@ xpc_setup_infrastructure(struct xpc_partition *part)
         * Allocate all of the channel structures as a contiguous chunk of
         * memory.
         */
-       part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
+       part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
                                                                GFP_KERNEL);
        if (part->channels == NULL) {
                dev_err(xpc_chan, "can't get memory for channels\n");
                return xpcNoMemory;
        }
-       memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS);
 
        part->nchannels = XPC_NCHANNELS;
 
 
        /* allocate all the required GET/PUT values */
 
-       part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+       part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
                                        GFP_KERNEL, &part->local_GPs_base);
        if (part->local_GPs == NULL) {
                kfree(part->channels);
@@ -115,55 +138,51 @@ xpc_setup_infrastructure(struct xpc_partition *part)
                        "values\n");
                return xpcNoMemory;
        }
-       memset(part->local_GPs, 0, XPC_GP_SIZE);
 
-       part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+       part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
                                        GFP_KERNEL, &part->remote_GPs_base);
        if (part->remote_GPs == NULL) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
                dev_err(xpc_chan, "can't get memory for remote get/put "
                        "values\n");
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcNoMemory;
        }
-       memset(part->remote_GPs, 0, XPC_GP_SIZE);
 
 
        /* allocate all the required open and close args */
 
-       part->local_openclose_args = xpc_kmalloc_cacheline_aligned(
+       part->local_openclose_args = xpc_kzalloc_cacheline_aligned(
                                        XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
                                        &part->local_openclose_args_base);
        if (part->local_openclose_args == NULL) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
+               dev_err(xpc_chan, "can't get memory for local connect args\n");
                kfree(part->remote_GPs_base);
                part->remote_GPs = NULL;
-               dev_err(xpc_chan, "can't get memory for local connect args\n");
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcNoMemory;
        }
-       memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
 
-       part->remote_openclose_args = xpc_kmalloc_cacheline_aligned(
+       part->remote_openclose_args = xpc_kzalloc_cacheline_aligned(
                                        XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
                                        &part->remote_openclose_args_base);
        if (part->remote_openclose_args == NULL) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
-               kfree(part->remote_GPs_base);
-               part->remote_GPs = NULL;
+               dev_err(xpc_chan, "can't get memory for remote connect args\n");
                kfree(part->local_openclose_args_base);
                part->local_openclose_args = NULL;
-               dev_err(xpc_chan, "can't get memory for remote connect args\n");
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcNoMemory;
        }
-       memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
 
 
        xpc_initialize_channels(part, partid);
@@ -186,18 +205,18 @@ xpc_setup_infrastructure(struct xpc_partition *part)
        ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ,
                                part->IPI_owner, (void *) (u64) partid);
        if (ret != 0) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
-               kfree(part->remote_GPs_base);
-               part->remote_GPs = NULL;
-               kfree(part->local_openclose_args_base);
-               part->local_openclose_args = NULL;
-               kfree(part->remote_openclose_args_base);
-               part->remote_openclose_args = NULL;
                dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
                        "errno=%d\n", -ret);
+               kfree(part->remote_openclose_args_base);
+               part->remote_openclose_args = NULL;
+               kfree(part->local_openclose_args_base);
+               part->local_openclose_args = NULL;
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcLackOfResources;
        }
 
@@ -446,22 +465,20 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
        for (nentries = ch->local_nentries; nentries > 0; nentries--) {
 
                nbytes = nentries * ch->msg_size;
-               ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+               ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
                                                GFP_KERNEL,
                                                &ch->local_msgqueue_base);
                if (ch->local_msgqueue == NULL) {
                        continue;
                }
-               memset(ch->local_msgqueue, 0, nbytes);
 
                nbytes = nentries * sizeof(struct xpc_notify);
-               ch->notify_queue = kmalloc(nbytes, GFP_KERNEL);
+               ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
                if (ch->notify_queue == NULL) {
                        kfree(ch->local_msgqueue_base);
                        ch->local_msgqueue = NULL;
                        continue;
                }
-               memset(ch->notify_queue, 0, nbytes);
 
                spin_lock_irqsave(&ch->lock, irq_flags);
                if (nentries < ch->local_nentries) {
@@ -501,13 +518,12 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
        for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
 
                nbytes = nentries * ch->msg_size;
-               ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+               ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
                                                GFP_KERNEL,
                                                &ch->remote_msgqueue_base);
                if (ch->remote_msgqueue == NULL) {
                        continue;
                }
-               memset(ch->remote_msgqueue, 0, nbytes);
 
                spin_lock_irqsave(&ch->lock, irq_flags);
                if (nentries < ch->remote_nentries) {
index 8cbf164325703048ecd277ebf141efb432e8b075..99b123a6421ad9541288b81f2148dfd9403161a4 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/syscalls.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/completion.h>
index 88a730e6cfdbc524e9a867f58c6cddb52e57b086..94211429fd0c0c821b445873c2b51c5edbc0f317 100644 (file)
@@ -80,6 +80,31 @@ char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
                                                        XP_NASID_MASK_BYTES];
 
 
+/*
+ * Guarantee that the kmalloc'd memory is cacheline aligned.
+ */
+static void *
+xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+{
+       /* see if kmalloc will give us cachline aligned memory by default */
+       *base = kmalloc(size, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+               return *base;
+       }
+       kfree(*base);
+
+       /* nope, we'll have to do it ourselves */
+       *base = kmalloc(size + L1_CACHE_BYTES, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       return (void *) L1_CACHE_ALIGN((u64) *base);
+}
+
+
 /*
  * Given a nasid, get the physical address of the  partition's reserved page
  * for that nasid. This function returns 0 on any error.
@@ -1038,13 +1063,12 @@ xpc_discovery(void)
        remote_vars = (struct xpc_vars *) remote_rp;
 
 
-       discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words,
+       discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
                                                        GFP_KERNEL);
        if (discovered_nasids == NULL) {
                kfree(remote_rp_base);
                return;
        }
-       memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
 
        rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
 
index e52831ed93ebc646ab599c89f15ffb210cc2461e..fa073cc4b565fc6dbf535cfdbe32fec1e7aa8b28 100644 (file)
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioce_provider.h>
+#include <asm/sn/sn2/sn_hwperf.h>
+
+/*
+ * 1/26/2006
+ *
+ * WAR for SGI PV 944642.  For revA TIOCE, need to use the following recipe
+ * (taken from the above PV) before and after accessing tioce internal MMR's
+ * to avoid tioce lockups.
+ *
+ * The recipe as taken from the PV:
+ *
+ *     if(mmr address < 0x45000) {
+ *             if(mmr address == 0 or 0x80)
+ *                     mmr wrt or read address 0xc0
+ *             else if(mmr address == 0x148 or 0x200)
+ *                     mmr wrt or read address 0x28
+ *             else
+ *                     mmr wrt or read address 0x158
+ *
+ *             do desired mmr access (rd or wrt)
+ *
+ *             if(mmr address == 0x100)
+ *                     mmr wrt or read address 0x38
+ *             mmr wrt or read address 0xb050
+ *     } else
+ *             do desired mmr access
+ *
+ * According to hw, we can use reads instead of writes to the above addres
+ *
+ * Note this WAR can only to be used for accessing internal MMR's in the
+ * TIOCE Coretalk Address Range 0x0 - 0x07ff_ffff.  This includes the
+ * "Local CE Registers and Memories" and "PCI Compatible Config Space" address
+ * spaces from table 2-1 of the "CE Programmer's Reference Overview" document.
+ *
+ * All registers defined in struct tioce will meet that criteria.
+ */
+
+static void inline
+tioce_mmr_war_pre(struct tioce_kernel *kern, void *mmr_addr)
+{
+       u64 mmr_base;
+       u64 mmr_offset;
+
+       if (kern->ce_common->ce_rev != TIOCE_REV_A)
+               return;
+
+       mmr_base = kern->ce_common->ce_pcibus.bs_base;
+       mmr_offset = (u64)mmr_addr - mmr_base;
+
+       if (mmr_offset < 0x45000) {
+               u64 mmr_war_offset;
+
+               if (mmr_offset == 0 || mmr_offset == 0x80)
+                       mmr_war_offset = 0xc0;
+               else if (mmr_offset == 0x148 || mmr_offset == 0x200)
+                       mmr_war_offset = 0x28;
+               else
+                       mmr_war_offset = 0x158;
+
+               readq_relaxed((void *)(mmr_base + mmr_war_offset));
+       }
+}
+
+static void inline
+tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr)
+{
+       u64 mmr_base;
+       u64 mmr_offset;
+
+       if (kern->ce_common->ce_rev != TIOCE_REV_A)
+               return;
+
+       mmr_base = kern->ce_common->ce_pcibus.bs_base;
+       mmr_offset = (u64)mmr_addr - mmr_base;
+
+       if (mmr_offset < 0x45000) {
+               if (mmr_offset == 0x100)
+                       readq_relaxed((void *)(mmr_base + 0x38));
+               readq_relaxed((void *)(mmr_base + 0xb050));
+       }
+}
+
+/* load mmr contents into a variable */
+#define tioce_mmr_load(kern, mmrp, varp) do {\
+       tioce_mmr_war_pre(kern, mmrp); \
+       *(varp) = readq_relaxed(mmrp); \
+       tioce_mmr_war_post(kern, mmrp); \
+} while (0)
+
+/* store variable contents into mmr */
+#define tioce_mmr_store(kern, mmrp, varp) do {\
+       tioce_mmr_war_pre(kern, mmrp); \
+       writeq(*varp, mmrp); \
+       tioce_mmr_war_post(kern, mmrp); \
+} while (0)
+
+/* store immediate value into mmr */
+#define tioce_mmr_storei(kern, mmrp, val) do {\
+       tioce_mmr_war_pre(kern, mmrp); \
+       writeq(val, mmrp); \
+       tioce_mmr_war_post(kern, mmrp); \
+} while (0)
+
+/* set bits (immediate value) into mmr */
+#define tioce_mmr_seti(kern, mmrp, bits) do {\
+       u64 tmp; \
+       tioce_mmr_load(kern, mmrp, &tmp); \
+       tmp |= (bits); \
+       tioce_mmr_store(kern, mmrp, &tmp); \
+} while (0)
+
+/* clear bits (immediate value) into mmr */
+#define tioce_mmr_clri(kern, mmrp, bits) do { \
+       u64 tmp; \
+       tioce_mmr_load(kern, mmrp, &tmp); \
+       tmp &= ~(bits); \
+       tioce_mmr_store(kern, mmrp, &tmp); \
+} while (0)
 
 /**
  * Bus address ranges for the 5 flavors of TIOCE DMA
 #define TIOCE_ATE_M40  2
 #define TIOCE_ATE_M40S 3
 
-#define KB(x)  ((x) << 10)
-#define MB(x)  ((x) << 20)
-#define GB(x)  ((x) << 30)
+#define KB(x)  ((u64)(x) << 10)
+#define MB(x)  ((u64)(x) << 20)
+#define GB(x)  ((u64)(x) << 30)
 
 /**
  * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode
@@ -151,7 +269,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
        int last;
        int entries;
        int nates;
-       int pagesize;
+       u64 pagesize;
        u64 *ate_shadow;
        u64 *ate_reg;
        u64 addr;
@@ -228,7 +346,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 
                ate = ATE_MAKE(addr, pagesize);
                ate_shadow[i + j] = ate;
-               writeq(ate, &ate_reg[i + j]);
+               tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate);
                addr += pagesize;
        }
 
@@ -272,7 +390,8 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
                u64 tmp;
 
                ce_kern->ce_port[port].dirmap_shadow = ct_upper;
-               writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]);
+               tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port],
+                                ct_upper);
                tmp = ce_mmr->ce_ure_dir_map[port];
                dma_ok = 1;
        } else
@@ -344,7 +463,8 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
        if (TIOCE_D32_ADDR(bus_addr)) {
                if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
                        ce_kern->ce_port[port].dirmap_shadow = 0;
-                       writeq(0, &ce_mmr->ce_ure_dir_map[port]);
+                       tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port],
+                                        0);
                }
        } else {
                struct tioce_dmamap *map;
@@ -365,7 +485,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
                } else if (--map->refcnt == 0) {
                        for (i = 0; i < map->ate_count; i++) {
                                map->ate_shadow[i] = 0;
-                               map->ate_hw[i] = 0;
+                               tioce_mmr_storei(ce_kern, &map->ate_hw[i], 0);
                        }
 
                        list_del(&map->ce_dmamap_list);
@@ -486,7 +606,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
        spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
 
 dma_map_done:
-       if (mapaddr & barrier)
+       if (mapaddr && barrier)
                mapaddr = tioce_dma_barrier(mapaddr, 1);
 
        return mapaddr;
@@ -541,17 +661,61 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
                        soft->ce_pcibus.bs_persist_segment,
                        soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0);
 
+       if (ret_stuff.v0)
+               panic("tioce_error_intr_handler:  Fatal TIOCE error");
+
        return IRQ_HANDLED;
 }
 
+/**
+ * tioce_reserve_m32 - reserve M32 ate's for the indicated address range
+ * @tioce_kernel: TIOCE context to reserve ate's for
+ * @base: starting bus address to reserve
+ * @limit: last bus address to reserve
+ *
+ * If base/limit falls within the range of bus space mapped through the
+ * M32 space, reserve the resources corresponding to the range.
+ */
+static void
+tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
+{
+       int ate_index, last_ate, ps;
+       struct tioce *ce_mmr;
+
+       if (!TIOCE_M32_ADDR(base))
+               return;
+
+       ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
+       ps = ce_kern->ce_ate3240_pagesize;
+       ate_index = ATE_PAGE(base, ps);
+       last_ate = ate_index + ATE_NPAGES(base, limit-base+1, ps) - 1;
+
+       if (ate_index < 64)
+               ate_index = 64;
+
+       while (ate_index <= last_ate) {
+               u64 ate;
+
+               ate = ATE_MAKE(0xdeadbeef, ps);
+               ce_kern->ce_ate3240_shadow[ate_index] = ate;
+               tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index],
+                                ate);
+               ate_index++;
+       }
+}
+
 /**
  * tioce_kern_init - init kernel structures related to a given TIOCE
  * @tioce_common: ptr to a cached tioce_common struct that originated in prom
- */ static struct tioce_kernel *
+ */
+static struct tioce_kernel *
 tioce_kern_init(struct tioce_common *tioce_common)
 {
        int i;
+       int ps;
+       int dev;
        u32 tmp;
+       unsigned int seg, bus;
        struct tioce *tioce_mmr;
        struct tioce_kernel *tioce_kern;
 
@@ -572,9 +736,10 @@ tioce_kern_init(struct tioce_common *tioce_common)
         * here to use pci_read_config_xxx() so use the raw_pci_ops vector.
         */
 
-       raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment,
-                         tioce_common->ce_pcibus.bs_persist_busnum,
-                         PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp);
+       seg = tioce_common->ce_pcibus.bs_persist_segment;
+       bus = tioce_common->ce_pcibus.bs_persist_busnum;
+
+       raw_pci_ops->read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
        tioce_kern->ce_port1_secondary = (u8) tmp;
 
        /*
@@ -583,18 +748,76 @@ tioce_kern_init(struct tioce_common *tioce_common)
         */
 
        tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
-       __sn_clrq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_PAGESIZE_MASK);
-       __sn_setq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_256K_PAGESIZE);
-       tioce_kern->ce_ate3240_pagesize = KB(256);
+       tioce_mmr_clri(tioce_kern, &tioce_mmr->ce_ure_page_map,
+                      CE_URE_PAGESIZE_MASK);
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_ure_page_map,
+                      CE_URE_256K_PAGESIZE);
+       ps = tioce_kern->ce_ate3240_pagesize = KB(256);
 
        for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
                tioce_kern->ce_ate40_shadow[i] = 0;
-               writeq(0, &tioce_mmr->ce_ure_ate40[i]);
+               tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate40[i], 0);
        }
 
        for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
                tioce_kern->ce_ate3240_shadow[i] = 0;
-               writeq(0, &tioce_mmr->ce_ure_ate3240[i]);
+               tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate3240[i], 0);
+       }
+
+       /*
+        * Reserve ATE's corresponding to reserved address ranges.  These
+        * include:
+        *
+        *      Memory space covered by each PPB mem base/limit register
+        *      Memory space covered by each PPB prefetch base/limit register
+        *
+        * These bus ranges are for pio (downstream) traffic only, and so
+        * cannot be used for DMA.
+        */
+
+       for (dev = 1; dev <= 2; dev++) {
+               u64 base, limit;
+
+               /* mem base/limit */
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_MEMORY_BASE, 2, &tmp);
+               base = (u64)tmp << 16;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_MEMORY_LIMIT, 2, &tmp);
+               limit = (u64)tmp << 16;
+               limit |= 0xfffffUL;
+
+               if (base < limit)
+                       tioce_reserve_m32(tioce_kern, base, limit);
+
+               /*
+                * prefetch mem base/limit.  The tioce ppb's have 64-bit
+                * decoders, so read the upper portions w/o checking the
+                * attributes.
+                */
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_MEMORY_BASE, 2, &tmp);
+               base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_BASE_UPPER32, 4, &tmp);
+               base |= (u64)tmp << 32;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_MEMORY_LIMIT, 2, &tmp);
+
+               limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
+               limit |= 0xfffffUL;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_LIMIT_UPPER32, 4, &tmp);
+               limit |= (u64)tmp << 32;
+
+               if ((base < limit) && TIOCE_M32_ADDR(base))
+                       tioce_reserve_m32(tioce_kern, base, limit);
        }
 
        return tioce_kern;
@@ -614,6 +837,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
 {
        struct pcidev_info *pcidev_info;
        struct tioce_common *ce_common;
+       struct tioce_kernel *ce_kern;
        struct tioce *ce_mmr;
        u64 force_int_val;
 
@@ -629,6 +853,29 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
 
        ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
        ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+       ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
+
+       /*
+        * TIOCE Rev A workaround (PV 945826), force an interrupt by writing
+        * the TIO_INTx register directly (1/26/2006)
+        */
+       if (ce_common->ce_rev == TIOCE_REV_A) {
+               u64 int_bit_mask = (1ULL << sn_irq_info->irq_int_bit);
+               u64 status;
+
+               tioce_mmr_load(ce_kern, &ce_mmr->ce_adm_int_status, &status);
+               if (status & int_bit_mask) {
+                       u64 force_irq = (1 << 8) | sn_irq_info->irq_irq;
+                       u64 ctalk = sn_irq_info->irq_xtalkaddr;
+                       u64 nasid, offset;
+
+                       nasid = (ctalk & CTALK_NASID_MASK) >> CTALK_NASID_SHFT;
+                       offset = (ctalk & CTALK_NODE_OFFSET);
+                       HUB_S(TIO_IOSPACE_ADDR(nasid, offset), force_irq);
+               }
+
+               return;
+       }
 
        /*
         * irq_int_bit is originally set up by prom, and holds the interrupt
@@ -666,7 +913,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
        default:
                return;
        }
-       writeq(force_int_val, &ce_mmr->ce_adm_force_int);
+       tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_force_int, force_int_val);
 }
 
 /**
@@ -685,6 +932,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 {
        struct pcidev_info *pcidev_info;
        struct tioce_common *ce_common;
+       struct tioce_kernel *ce_kern;
        struct tioce *ce_mmr;
        int bit;
        u64 vector;
@@ -695,14 +943,15 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 
        ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
        ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+       ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
 
        bit = sn_irq_info->irq_int_bit;
 
-       __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
+       tioce_mmr_seti(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit));
        vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
        vector |= sn_irq_info->irq_xtalkaddr;
-       writeq(vector, &ce_mmr->ce_adm_int_dest[bit]);
-       __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
+       tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_int_dest[bit], vector);
+       tioce_mmr_clri(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit));
 
        tioce_force_interrupt(sn_irq_info);
 }
@@ -721,7 +970,11 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 static void *
 tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
 {
+       int my_nasid;
+       cnodeid_t my_cnode, mem_cnode;
        struct tioce_common *tioce_common;
+       struct tioce_kernel *tioce_kern;
+       struct tioce *tioce_mmr;
 
        /*
         * Allocate kernel bus soft and copy from prom.
@@ -734,11 +987,23 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
        memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
        tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET;
 
-       if (tioce_kern_init(tioce_common) == NULL) {
+       tioce_kern = tioce_kern_init(tioce_common);
+       if (tioce_kern == NULL) {
                kfree(tioce_common);
                return NULL;
        }
 
+       /*
+        * Clear out any transient errors before registering the error
+        * interrupt handler.
+        */
+
+       tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL);
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias,
+                      ~0ULL);
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL);
+
        if (request_irq(SGI_PCIASIC_ERROR,
                        tioce_error_intr_handler,
                        SA_SHIRQ, "TIOCE error", (void *)tioce_common))
@@ -750,6 +1015,21 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
                       tioce_common->ce_pcibus.bs_persist_segment,
                       tioce_common->ce_pcibus.bs_persist_busnum);
 
+       /*
+        * identify closest nasid for memory allocations
+        */
+
+       my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base);
+       my_cnode = nasid_to_cnodeid(my_nasid);
+
+       if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) {
+               printk(KERN_WARNING "tioce_bus_fixup: failed to find "
+                      "closest node with MEM to TIO node %d\n", my_cnode);
+               mem_cnode = (cnodeid_t)-1; /* use any node */
+       }
+
+       controller->node = mem_cnode;
+
        return tioce_common;
 }
 
index 6facf15b04f30d1353840e65fa8362fc664c4be1..c9e7dad860b741cf02e1b42022c91226c27388d9 100644 (file)
@@ -226,7 +226,7 @@ void free_initmem(void)
        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
@@ -244,7 +244,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        unsigned long p;
        for (p = start; p < end; p += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(p));
-               set_page_count(virt_to_page(p), 1);
+               init_page_count(virt_to_page(p));
                free_page(p);
                totalram_pages++;
        }
index c45beb955943d6c1d5e3c89e6917b8de9ec0bca3..a190e39c907ad747fc3a2ab336a9da2745e79e3c 100644 (file)
@@ -137,7 +137,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        int pages = 0;
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
                pages++;
index 559942ce0e1e7bde2773ac90f5150dca5e542e5e..d6d582a5abb001b49114a05a71e6204a37a9f39e 100644 (file)
@@ -54,7 +54,7 @@ void __init init_pointer_table(unsigned long ptable)
 
        /* unreserve the page so it's possible to free that page */
        PD_PAGE(dp)->flags &= ~(1 << PG_reserved);
-       set_page_count(PD_PAGE(dp), 1);
+       init_page_count(PD_PAGE(dp));
 
        return;
 }
index d855fec263172c0ad0bb65ffa67a8121066e71fc..afb57eeafdcb191c68a22058db46a6ba9044686e 100644 (file)
@@ -276,7 +276,7 @@ void free_initmem(void)
        addr = (unsigned long)&__init_begin;
        for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
                virt_to_page(addr)->flags &= ~(1 << PG_reserved);
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
index eddb8d3e130ab116e7957349e2a17beb0566646b..d844c755945a2c3df9343cd7739c7a6d0563acca 100644 (file)
@@ -26,6 +26,7 @@ EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
index 89f0b554ffb79fb8acfc2d62e7487f75ce61e09e..d79503fe6e42f4d81a4cf9331d7cba0e387191ec 100644 (file)
@@ -195,7 +195,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        int pages = 0;
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
                pages++;
@@ -218,7 +218,7 @@ free_initmem()
        /* next to check that the page we free is not a partial page */
        for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
index 958d2eb78862e5f66c18fa0747b0bb69b9f02fab..8a9ef58cc399313b2b46125cf0b207cc4c9ce2ab 100644 (file)
@@ -158,7 +158,7 @@ unsigned long __init prom_free_prom_memory(void)
                while (addr < boot_mem_map.map[i].addr
                              + boot_mem_map.map[i].size) {
                        ClearPageReserved(virt_to_page(__va(addr)));
-                       set_page_count(virt_to_page(__va(addr)), 1);
+                       init_page_count(virt_to_page(__va(addr)));
                        free_page((unsigned long)__va(addr));
                        addr += PAGE_SIZE;
                        freed += PAGE_SIZE;
index 81cb5a76cfb7b9b07e3acf3616902cf1cace0879..1edaf3074ee93f9bed2c287b21619b6c6fda7419 100644 (file)
@@ -118,7 +118,7 @@ unsigned long __init prom_free_prom_memory(void)
        addr = PAGE_SIZE;
        while (addr < end) {
                ClearPageReserved(virt_to_page(__va(addr)));
-               set_page_count(virt_to_page(__va(addr)), 1);
+               init_page_count(virt_to_page(__va(addr)));
                free_page((unsigned long)__va(addr));
                addr += PAGE_SIZE;
        }
index 2c8afd77a20b2a4f9df12a4923b4a8e8c8409627..ee5e70c95cf3fbdadd877ebd347231d6df955cab 100644 (file)
@@ -174,7 +174,7 @@ unsigned long __init prom_free_prom_memory(void)
                while (addr < boot_mem_map.map[i].addr
                              + boot_mem_map.map[i].size) {
                        ClearPageReserved(virt_to_page(__va(addr)));
-                       set_page_count(virt_to_page(__va(addr)), 1);
+                       init_page_count(virt_to_page(__va(addr)));
                        free_page((unsigned long)__va(addr));
                        addr += PAGE_SIZE;
                        freed += PAGE_SIZE;
index 0dbd7435bb2aff83985e0ad25360d93ab13f04de..1ec4e75656bd11c395559c9a65b1fff628becd56 100644 (file)
@@ -117,7 +117,7 @@ unsigned long __init prom_free_prom_memory(void)
                while (addr < boot_mem_map.map[i].addr
                              + boot_mem_map.map[i].size) {
                        ClearPageReserved(virt_to_page(__va(addr)));
-                       set_page_count(virt_to_page(__va(addr)), 1);
+                       init_page_count(virt_to_page(__va(addr)));
                        free_page((unsigned long)__va(addr));
                        addr += PAGE_SIZE;
                        freed += PAGE_SIZE;
index 0ff9a348b84317b2c915de9aeb485839fb1ff1ce..52f7d59fe6123b28469802a36120722e6224f365 100644 (file)
@@ -54,7 +54,8 @@ unsigned long empty_zero_page, zero_page_mask;
  */
 unsigned long setup_zero_pages(void)
 {
-       unsigned long order, size;
+       unsigned int order;
+       unsigned long size;
        struct page *page;
 
        if (cpu_has_vce)
@@ -67,9 +68,9 @@ unsigned long setup_zero_pages(void)
                panic("Oh boy, that early out of memory?");
 
        page = virt_to_page(empty_zero_page);
+       split_page(page, order);
        while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
                SetPageReserved(page);
-               set_page_count(page, 1);
                page++;
        }
 
@@ -244,7 +245,7 @@ void __init mem_init(void)
 #ifdef CONFIG_LIMITED_DMA
                set_page_address(page, lowmem_page_address(page));
 #endif
-               set_page_count(page, 1);
+               init_page_count(page);
                __free_page(page);
                totalhigh_pages++;
        }
@@ -291,7 +292,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
@@ -314,7 +315,7 @@ void free_initmem(void)
                page = addr;
 #endif
                ClearPageReserved(virt_to_page(page));
-               set_page_count(virt_to_page(page), 1);
+               init_page_count(virt_to_page(page));
                free_page(page);
                totalram_pages++;
                freed += PAGE_SIZE;
index ed93a9792959f240555f1746dd28daaa97dff506..e0d095daa5ed76782116ed5909d751e41345404f 100644 (file)
@@ -559,7 +559,7 @@ void __init mem_init(void)
                                /* if (!page_is_ram(pgnr)) continue; */
                                /* commented out until page_is_ram works */
                                ClearPageReserved(p);
-                               set_page_count(p, 1);
+                               init_page_count(p);
                                __free_page(p);
                                totalram_pages++;
                        }
index 7847ca13d6c2933b2be345e8d73a9ffd3d1229db..852eda3953dc7c86114e0b7cdeff08775485ed43 100644 (file)
@@ -398,7 +398,7 @@ void free_initmem(void)
        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                num_physpages++;
                totalram_pages++;
@@ -1018,7 +1018,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                num_physpages++;
                totalram_pages++;
index b51bb28c054bbb5e14007af0d9efee7be0806a3a..7370f9f33e2943d038025a6d05ba6b4e02755beb 100644 (file)
@@ -133,21 +133,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
        return __pte(old);
 }
 
-/*
- * This function checks for proper alignment of input addr and len parameters.
- */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
-{
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-       if (! (within_hugepage_low_range(addr, len)
-              || within_hugepage_high_range(addr, len)) )
-               return -EINVAL;
-       return 0;
-}
-
 struct slb_flush_info {
        struct mm_struct *mm;
        u16 newareas;
index 7d0d75c11848ec7ca0e1c8b0468e7958e47a1331..b57fb3a2b7bb25767d10596f978a5ed4df985c47 100644 (file)
@@ -216,7 +216,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name)
 
        while (start < end) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                cnt++;
                start += PAGE_SIZE;
@@ -248,7 +248,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
index 81cfb0c2ec58bf5bd1d056b48206b551b1aad935..bacb71c89811b27c48f8e5f05b8dbf3dbe27fd3f 100644 (file)
@@ -140,7 +140,7 @@ void free_initmem(void)
        for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
                memset((void *)addr, 0xcc, PAGE_SIZE);
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
@@ -155,7 +155,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
index 550517c2dd42babc88c7064763556b5851467dd4..454cac01d8cc0667dfee9314372153d32adeefbf 100644 (file)
@@ -108,8 +108,8 @@ EXPORT_SYMBOL(phys_mem_access_prot);
 void online_page(struct page *page)
 {
        ClearPageReserved(page);
-       set_page_count(page, 0);
-       free_cold_page(page);
+       init_page_count(page);
+       __free_page(page);
        totalram_pages++;
        num_physpages++;
 }
@@ -376,7 +376,7 @@ void __init mem_init(void)
                        struct page *page = pfn_to_page(pfn);
 
                        ClearPageReserved(page);
-                       set_page_count(page, 1);
+                       init_page_count(page);
                        __free_page(page);
                        totalhigh_pages++;
                }
index b33a4443f5a9368344f6ac3f3507ac6593a86e77..fec8e65b36ea421a7f5f879acf2efe3ce00c5d0c 100644 (file)
@@ -115,7 +115,7 @@ static void __init cell_spuprop_present(struct device_node *spe,
                for (pfn = start_pfn; pfn < end_pfn; pfn++) {
                        struct page *page = pfn_to_page(pfn);
                        set_page_links(page, ZONE_DMA, node_id, pfn);
-                       set_page_count(page, 1);
+                       init_page_count(page);
                        reset_page_mapcount(page);
                        SetPageReserved(page);
                        INIT_LIST_HEAD(&page->lru);
index 685fd0defe23484772bf89e99b772bd9cbd65486..61465ec88bc7268b0325001bac308c28d1db8588 100644 (file)
@@ -223,6 +223,8 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
                pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
                struct page *end = page + (1 << order);
 
+               split_page(page, order);
+
                /*
                 * Set the "dma handle"
                 */
@@ -231,7 +233,6 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
                do {
                        BUG_ON(!pte_none(*pte));
 
-                       set_page_count(page, 1);
                        SetPageReserved(page);
                        set_pte_at(&init_mm, vaddr,
                                   pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
@@ -244,7 +245,6 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
                 * Free the otherwise unused pages.
                 */
                while (page < end) {
-                       set_page_count(page, 1);
                        __free_page(page);
                        page++;
                }
index 134db5c0420319bbe31888b6b06cb3844849e214..cb1c294fb932678a9d32429b5022582de7518f8b 100644 (file)
@@ -140,7 +140,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name)
 
        while (start < end) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                cnt++;
                start += PAGE_SIZE;
@@ -172,7 +172,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
@@ -441,7 +441,7 @@ void __init mem_init(void)
                        struct page *page = mem_map + pfn;
 
                        ClearPageReserved(page);
-                       set_page_count(page, 1);
+                       init_page_count(page);
                        __free_page(page);
                        totalhigh_pages++;
                }
index df953383724d9d0686997e7e931f3c98ad40becb..a055894f3bd89a59f4e843c1c113ef5ce80547aa 100644 (file)
@@ -292,7 +292,7 @@ void free_initmem(void)
         addr = (unsigned long)(&__init_begin);
         for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
         }
@@ -307,7 +307,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                 printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
         for (; start < end; start += PAGE_SIZE) {
                 ClearPageReserved(virt_to_page(start));
-                set_page_count(virt_to_page(start), 1);
+                init_page_count(virt_to_page(start));
                 free_page(start);
                 totalram_pages++;
         }
index df3a9e452cc55321c238143b05190557401bb867..ee73e30263af947b683e2833bb88e52806151f21 100644 (file)
@@ -23,6 +23,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
        page = alloc_pages(gfp, order);
        if (!page)
                return NULL;
+       split_page(page, order);
 
        ret = page_address(page);
        *handle = virt_to_phys(ret);
@@ -37,8 +38,6 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
        end  = page + (1 << order);
 
        while (++page < end) {
-               set_page_count(page, 1);
-
                /* Free any unused pages */
                if (page >= free) {
                        __free_page(page);
index 6b7a7688c98e87178d4915a1f17e8118213a5e63..a3568fd51508e4435dfb217f4c6d42089dc7ea0c 100644 (file)
@@ -84,18 +84,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
        return entry;
 }
 
-/*
- * This function checks for proper alignment of input addr and len parameters.
- */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
-{
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-       return 0;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
                              unsigned long address, int write)
 {
index e342565f75fbc464684faf8e54f28e05134475ea..77b4a838fe10f494e9c0896c06479f9abb699721 100644 (file)
@@ -273,7 +273,7 @@ void free_initmem(void)
        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
@@ -286,7 +286,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        unsigned long p;
        for (p = start; p < end; p += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(p));
-               set_page_count(virt_to_page(p), 1);
+               init_page_count(virt_to_page(p));
                free_page(p);
                totalram_pages++;
        }
index ed6a505b3ee2b9e7194268449067c8e8746ae681..3d89f2a6c785cf70582cac9d231fb4e729e8eb01 100644 (file)
@@ -84,18 +84,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
        return entry;
 }
 
-/*
- * This function checks for proper alignment of input addr and len parameters.
- */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
-{
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-       return 0;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
                              unsigned long address, int write)
 {
index a65e8bb2c3cc5e8cbf644799d4f3ffdda0d4fdaa..1169757fb38b1cfe05ab454a77ca01cc06c00c51 100644 (file)
@@ -173,7 +173,7 @@ void free_initmem(void)
        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                free_page(addr);
                totalram_pages++;
        }
@@ -186,7 +186,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        unsigned long p;
        for (p = start; p < end; p += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(p));
-               set_page_count(virt_to_page(p), 1);
+               init_page_count(virt_to_page(p));
                free_page(p);
                totalram_pages++;
        }
index 40d426cce8244f16969e3a12f876855f0893bd0f..4219dd2ce3a2332094340c731d4142f4b569c461 100644 (file)
@@ -266,19 +266,19 @@ void __init smp4d_boot_cpus(void)
 
        /* Free unneeded trap tables */
        ClearPageReserved(virt_to_page(trapbase_cpu1));
-       set_page_count(virt_to_page(trapbase_cpu1), 1);
+       init_page_count(virt_to_page(trapbase_cpu1));
        free_page((unsigned long)trapbase_cpu1);
        totalram_pages++;
        num_physpages++;
 
        ClearPageReserved(virt_to_page(trapbase_cpu2));
-       set_page_count(virt_to_page(trapbase_cpu2), 1);
+       init_page_count(virt_to_page(trapbase_cpu2));
        free_page((unsigned long)trapbase_cpu2);
        totalram_pages++;
        num_physpages++;
 
        ClearPageReserved(virt_to_page(trapbase_cpu3));
-       set_page_count(virt_to_page(trapbase_cpu3), 1);
+       init_page_count(virt_to_page(trapbase_cpu3));
        free_page((unsigned long)trapbase_cpu3);
        totalram_pages++;
        num_physpages++;
index a21f27d10e55737881f81522262b4e07751476e9..fbbd8a474c4c62bfbc47ac5949f835c3dcad2a1f 100644 (file)
@@ -233,21 +233,21 @@ void __init smp4m_boot_cpus(void)
        /* Free unneeded trap tables */
        if (!cpu_isset(i, cpu_present_map)) {
                ClearPageReserved(virt_to_page(trapbase_cpu1));
-               set_page_count(virt_to_page(trapbase_cpu1), 1);
+               init_page_count(virt_to_page(trapbase_cpu1));
                free_page((unsigned long)trapbase_cpu1);
                totalram_pages++;
                num_physpages++;
        }
        if (!cpu_isset(2, cpu_present_map)) {
                ClearPageReserved(virt_to_page(trapbase_cpu2));
-               set_page_count(virt_to_page(trapbase_cpu2), 1);
+               init_page_count(virt_to_page(trapbase_cpu2));
                free_page((unsigned long)trapbase_cpu2);
                totalram_pages++;
                num_physpages++;
        }
        if (!cpu_isset(3, cpu_present_map)) {
                ClearPageReserved(virt_to_page(trapbase_cpu3));
-               set_page_count(virt_to_page(trapbase_cpu3), 1);
+               init_page_count(virt_to_page(trapbase_cpu3));
                free_page((unsigned long)trapbase_cpu3);
                totalram_pages++;
                num_physpages++;
index c03babaa0498b95787eac1bd3ec2244364208339..898669732466a2a51994efb09557ff75a546918d 100644 (file)
@@ -383,7 +383,7 @@ void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
                struct page *page = pfn_to_page(tmp);
 
                ClearPageReserved(page);
-               set_page_count(page, 1);
+               init_page_count(page);
                __free_page(page);
                totalhigh_pages++;
        }
@@ -480,7 +480,7 @@ void free_initmem (void)
                p = virt_to_page(addr);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                totalram_pages++;
                num_physpages++;
@@ -497,7 +497,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                struct page *p = virt_to_page(start);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                num_physpages++;
        }
index a7a24869d04576b67ec56216e474fef4ff3632a8..280dc7958a13784a5485a0d3be6681cb5c2d8dea 100644 (file)
@@ -263,18 +263,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
        return entry;
 }
 
-/*
- * This function checks for proper alignment of input addr and len parameters.
- */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
-{
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-       return 0;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
                              unsigned long address, int write)
 {
index c2b556106fc175cad9e92cef28eb9f99237392a9..2ae143ba50d82c994d24f1523ed93928d982e5df 100644 (file)
@@ -1461,7 +1461,7 @@ void free_initmem(void)
                p = virt_to_page(page);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                num_physpages++;
                totalram_pages++;
@@ -1477,7 +1477,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                struct page *p = virt_to_page(start);
 
                ClearPageReserved(p);
-               set_page_count(p, 1);
+               init_page_count(p);
                __free_page(p);
                num_physpages++;
                totalram_pages++;
index fa4f915be5c59e15fb5c393e12f40e0a0f77f24e..92cce96b5e24d01f50d7502ba81f1b64e98a1683 100644 (file)
@@ -57,7 +57,7 @@ static void setup_highmem(unsigned long highmem_start,
        for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
                page = &mem_map[highmem_pfn + i];
                ClearPageReserved(page);
-               set_page_count(page, 1);
+               init_page_count(page);
                __free_page(page);
        }
 }
@@ -296,7 +296,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                        (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
index 544665e04513b33b4106ccd564be392e22d09b8f..0e65340eee33704f141621b46cc2641de0e4f949 100644 (file)
@@ -279,7 +279,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
 
        for(i = 0; i < total_pages; i++){
                p = &map[i];
-               set_page_count(p, 0);
+               memset(p, 0, sizeof(struct page));
                SetPageReserved(p);
                INIT_LIST_HEAD(&p->lru);
        }
index 3080f84bf7b76f8f68274d84c5af15d705afc625..ee5ce3d3cbc3e8c50c2bdbaba99070e3e64d9957 100644 (file)
@@ -477,7 +477,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-static unsigned int cyc2ns_scale;
+static unsigned int cyc2ns_scale __read_mostly;
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
 static inline void set_cyc2ns_scale(unsigned long cpu_khz)
index 3496abc8d372eb1dfe57297d032f670c2d839af9..c9dc7e46731e1cc4878c0cc59fa2fa8695d660a5 100644 (file)
@@ -124,6 +124,7 @@ extern void * __memcpy(void *,const void *,__kernel_size_t);
 
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
index 7af1742aa958a8f6247a1e323a9b2c6f45d75bf5..40ed13d263cd5ccccb6a210cee4b0005927822fc 100644 (file)
@@ -486,7 +486,7 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
 void online_page(struct page *page)
 {
        ClearPageReserved(page);
-       set_page_count(page, 1);
+       init_page_count(page);
        __free_page(page);
        totalram_pages++;
        num_physpages++;
@@ -592,7 +592,7 @@ void free_initmem(void)
        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
-               set_page_count(virt_to_page(addr), 1);
+               init_page_count(virt_to_page(addr));
                memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); 
                free_page(addr);
                totalram_pages++;
@@ -632,7 +632,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page(start);
                totalram_pages++;
        }
index 35f1f1aab0638ac41699ec718980c26fd40b383d..531ad21447b1c95e4e5a9d9bc020f13784b01d7f 100644 (file)
@@ -45,6 +45,13 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
        pte_t *pbase;
        if (!base) 
                return NULL;
+       /*
+        * page_private is used to track the number of entries in
+        * the page table page have non standard attributes.
+        */
+       SetPagePrivate(base);
+       page_private(base) = 0;
+
        address = __pa(address);
        addr = address & LARGE_PAGE_MASK; 
        pbase = (pte_t *)page_address(base);
@@ -77,26 +84,12 @@ static inline void flush_map(unsigned long address)
        on_each_cpu(flush_kernel_map, (void *)address, 1, 1);
 }
 
-struct deferred_page { 
-       struct deferred_page *next; 
-       struct page *fpage;
-       unsigned long address;
-}; 
-static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */
+static struct page *deferred_pages; /* protected by init_mm.mmap_sem */
 
-static inline void save_page(unsigned long address, struct page *fpage)
+static inline void save_page(struct page *fpage)
 {
-       struct deferred_page *df;
-       df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); 
-       if (!df) {
-               flush_map(address);
-               __free_page(fpage);
-       } else { 
-               df->next = df_list;
-               df->fpage = fpage;
-               df->address = address;
-               df_list = df;
-       }                       
+       fpage->lru.next = (struct list_head *)deferred_pages;
+       deferred_pages = fpage;
 }
 
 /* 
@@ -138,8 +131,8 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
                        set_pte(kpte, pfn_pte(pfn, prot));
                } else {
                        /*
-                        * split_large_page will take the reference for this change_page_attr
-                        * on the split page.
+                        * split_large_page will take the reference for this
+                        * change_page_attr on the split page.
                         */
 
                        struct page *split;
@@ -151,23 +144,20 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
                        set_pte(kpte,mk_pte(split, ref_prot2));
                        kpte_page = split;
                }       
-               get_page(kpte_page);
+               page_private(kpte_page)++;
        } else if ((kpte_flags & _PAGE_PSE) == 0) { 
                set_pte(kpte, pfn_pte(pfn, ref_prot));
-               __put_page(kpte_page);
+               BUG_ON(page_private(kpte_page) == 0);
+               page_private(kpte_page)--;
        } else
                BUG();
 
        /* on x86-64 the direct mapping set at boot is not using 4k pages */
        BUG_ON(PageReserved(kpte_page));
 
-       switch (page_count(kpte_page)) {
-       case 1:
-               save_page(address, kpte_page);               
+       if (page_private(kpte_page) == 0) {
+               save_page(kpte_page);
                revert_page(address, ref_prot);
-               break;
-       case 0:
-               BUG(); /* memleak and failed 2M page regeneration */
        }
        return 0;
 } 
@@ -220,17 +210,18 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot)
 
 void global_flush_tlb(void)
 { 
-       struct deferred_page *df, *next_df;
+       struct page *dpage;
 
        down_read(&init_mm.mmap_sem);
-       df = xchg(&df_list, NULL);
+       dpage = xchg(&deferred_pages, NULL);
        up_read(&init_mm.mmap_sem);
-       flush_map((df && !df->next) ? df->address : 0);
-       for (; df; df = next_df) { 
-               next_df = df->next;
-               if (df->fpage) 
-                       __free_page(df->fpage);
-               kfree(df);
+
+       flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0);
+       while (dpage) {
+               struct page *tmp = dpage;
+               dpage = (struct page *)dpage->lru.next;
+               ClearPagePrivate(tmp);
+               __free_page(tmp);
        } 
 } 
 
index 5a91d6c9e66db45402c50ec487b127fd6901931c..e1be4235f3671a256ba89be01b45c9c4ff8c6a0a 100644 (file)
@@ -272,7 +272,7 @@ free_reserved_mem(void *start, void *end)
 {
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
-               set_page_count(virt_to_page(start), 1);
+               init_page_count(virt_to_page(start));
                free_page((unsigned long)start);
                totalram_pages++;
        }
index e5e119c820e4713d5badfd650c0a9792aca99e72..7d28914d11cbc63afcf131c7ee030288803441d9 100644 (file)
 
 pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       pte_t *ptep;
+       pte_t *pte = NULL, *p;
        int color = ADDR_COLOR(address);
        int i;
 
        p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER);
 
        if (likely(p)) {
-               struct page *page;
-
-               for (i = 0; i < COLOR_SIZE; i++, p++) {
-                       page = virt_to_page(pte);
-
-                       set_page_count(page, 1);
-                       ClearPageCompound(page);
+               split_page(virt_to_page(p), COLOR_ORDER);
 
+               for (i = 0; i < COLOR_SIZE; i++) {
                        if (ADDR_COLOR(p) == color)
                                pte = p;
                        else
                                free_page(p);
+                       p += PTRS_PER_PTE;
                }
                clear_page(pte);
        }
@@ -49,20 +45,20 @@ int flush;
 
 struct page* pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       struct page *pagep;
+       struct page *page = NULL, *p;
        int color = ADDR_COLOR(address);
 
        p = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
 
        if (likely(p)) {
-               for (i = 0; i < PAGE_ORDER; i++) {
-                       set_page_count(p, 1);
-                       ClearPageCompound(p);
+               split_page(p, COLOR_ORDER);
 
-                       if (PADDR_COLOR(page_address(pg)) == color)
+               for (i = 0; i < PAGE_ORDER; i++) {
+                       if (PADDR_COLOR(page_address(p)) == color)
                                page = p;
                        else
-                               free_page(p);
+                               __free_page(p);
+                       p++;
                }
                clear_highpage(page);
        }
index a9efc13cc8583e127070b8b19394773e4fecedbc..8a98169b60c1ad42cb240bf71202f30d1f4f1e33 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 /*
@@ -70,6 +70,9 @@ struct sysctl_data_s {
 #define EV_CLASS_TEST_WARNING  0x6000ul
 #define EV_CLASS_PWRD_NOTIFY   0x8000ul
 
+/* ENV class codes */
+#define ENV_PWRDN_PEND         0x4101ul
+
 #define EV_SEVERITY_POWER_STABLE       0x0000ul
 #define EV_SEVERITY_POWER_LOW_WARNING  0x0100ul
 #define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul
index baaa365285fa973776beddcb0ae5c09389ffbe65..a4fa507eed9e451824541891bf7e4f83920c49d2 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 /*
@@ -187,7 +187,8 @@ scdrv_event_severity(int code)
 static void
 scdrv_dispatch_event(char *event, int len)
 {
-       int code, esp_code, src;
+       static int snsc_shutting_down = 0;
+       int code, esp_code, src, class;
        char desc[CHUNKSIZE];
        char *severity;
 
@@ -199,9 +200,25 @@ scdrv_dispatch_event(char *event, int len)
        /* how urgent is the message? */
        severity = scdrv_event_severity(code);
 
-       if ((code & EV_CLASS_MASK) == EV_CLASS_PWRD_NOTIFY) {
+       class = (code & EV_CLASS_MASK);
+
+       if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) {
                struct task_struct *p;
 
+               if (snsc_shutting_down)
+                       return;
+
+               snsc_shutting_down = 1;
+
+               /* give a message for each type of event */
+               if (class == EV_CLASS_PWRD_NOTIFY)
+                       printk(KERN_NOTICE "Power off indication received."
+                              " Sending SIGPWR to init...\n");
+               else if (code == ENV_PWRDN_PEND)
+                       printk(KERN_CRIT "WARNING: Shutting down the system"
+                              " due to a critical environmental condition."
+                              " Sending SIGPWR to init...\n");
+
                /* give a SIGPWR signal to init proc */
 
                /* first find init's task */
@@ -210,12 +227,11 @@ scdrv_dispatch_event(char *event, int len)
                        if (p->pid == 1)
                                break;
                }
-               if (p) { /* we found init's task */
-                       printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n");
+               if (p) {
                        force_sig(SIGPWR, p);
-               } else { /* failed to find init's task - just give message(s) */
-                       printk(KERN_WARNING "Failed to find init proc to handle power off!\n");
-                       printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
+               } else {
+                       printk(KERN_ERR "Failed to signal init!\n");
+                       snsc_shutting_down = 0; /* so can try again (?) */
                }
                read_unlock(&tasklist_lock);
        } else {
index ac2a297ce37c5a23354fdeca5ec0d84ffaa18079..a80c83210872b544551573f214e5e9223c3921c6 100644 (file)
@@ -283,7 +283,7 @@ static void tb0219_pci_irq_init(void)
        vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
 }
 
-static int tb0219_probe(struct platform_device *dev)
+static int __devinit tb0219_probe(struct platform_device *dev)
 {
        int retval;
 
@@ -319,7 +319,7 @@ static int tb0219_probe(struct platform_device *dev)
        return 0;
 }
 
-static int tb0219_remove(struct platform_device *dev)
+static int __devexit tb0219_remove(struct platform_device *dev)
 {
        _machine_restart = old_machine_restart;
 
@@ -335,19 +335,26 @@ static struct platform_device *tb0219_platform_device;
 
 static struct platform_driver tb0219_device_driver = {
        .probe          = tb0219_probe,
-       .remove         = tb0219_remove,
+       .remove         = __devexit_p(tb0219_remove),
        .driver         = {
                .name   = "TB0219",
+               .owner  = THIS_MODULE,
        },
 };
 
-static int __devinit tanbac_tb0219_init(void)
+static int __init tanbac_tb0219_init(void)
 {
        int retval;
 
-       tb0219_platform_device = platform_device_register_simple("TB0219", -1, NULL, 0);
-       if (IS_ERR(tb0219_platform_device))
-               return PTR_ERR(tb0219_platform_device);
+       tb0219_platform_device = platform_device_alloc("TB0219", -1);
+       if (!tb0219_platform_device)
+               return -ENOMEM;
+
+       retval = platform_device_add(tb0219_platform_device);
+       if (retval < 0) {
+               platform_device_put(tb0219_platform_device);
+               return retval;
+       }
 
        retval = platform_driver_register(&tb0219_device_driver);
        if (retval < 0)
@@ -356,10 +363,9 @@ static int __devinit tanbac_tb0219_init(void)
        return retval;
 }
 
-static void __devexit tanbac_tb0219_exit(void)
+static void __exit tanbac_tb0219_exit(void)
 {
        platform_driver_unregister(&tb0219_device_driver);
-
        platform_device_unregister(tb0219_platform_device);
 }
 
index 2267c7b81799d5b2cdeb55d8d0cc787fd1bf7821..05e6e814d86fd64d4670dccd38fe8e1eb7132138 100644 (file)
@@ -613,7 +613,7 @@ static struct file_operations gpio_fops = {
        .release        = gpio_release,
 };
 
-static int giu_probe(struct platform_device *dev)
+static int __devinit giu_probe(struct platform_device *dev)
 {
        unsigned long start, size, flags = 0;
        unsigned int nr_pins = 0;
@@ -697,7 +697,7 @@ static int giu_probe(struct platform_device *dev)
        return cascade_irq(GIUINT_IRQ, giu_get_irq);
 }
 
-static int giu_remove(struct platform_device *dev)
+static int __devexit giu_remove(struct platform_device *dev)
 {
        iounmap(giu_base);
 
@@ -712,9 +712,10 @@ static struct platform_device *giu_platform_device;
 
 static struct platform_driver giu_device_driver = {
        .probe          = giu_probe,
-       .remove         = giu_remove,
+       .remove         = __devexit_p(giu_remove),
        .driver         = {
                .name   = "GIU",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -722,9 +723,15 @@ static int __init vr41xx_giu_init(void)
 {
        int retval;
 
-       giu_platform_device = platform_device_register_simple("GIU", -1, NULL, 0);
-       if (IS_ERR(giu_platform_device))
-               return PTR_ERR(giu_platform_device);
+       giu_platform_device = platform_device_alloc("GIU", -1);
+       if (!giu_platform_device)
+               return -ENOMEM;
+
+       retval = platform_device_add(giu_platform_device);
+       if (retval < 0) {
+               platform_device_put(giu_platform_device);
+               return retval;
+       }
 
        retval = platform_driver_register(&giu_device_driver);
        if (retval < 0)
index bc1b4a15212c2d939e4ed4508dcf5c70eacfe405..b109d9a502d63dfde26ba6c04a2083ed2bdd4b3d 100644 (file)
@@ -558,7 +558,7 @@ static struct miscdevice rtc_miscdevice = {
        .fops   = &rtc_fops,
 };
 
-static int rtc_probe(struct platform_device *pdev)
+static int __devinit rtc_probe(struct platform_device *pdev)
 {
        unsigned int irq;
        int retval;
@@ -631,7 +631,7 @@ static int rtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int rtc_remove(struct platform_device *dev)
+static int __devexit rtc_remove(struct platform_device *dev)
 {
        int retval;
 
@@ -653,13 +653,14 @@ static struct platform_device *rtc_platform_device;
 
 static struct platform_driver rtc_device_driver = {
        .probe          = rtc_probe,
-       .remove         = rtc_remove,
+       .remove         = __devexit_p(rtc_remove),
        .driver         = {
                .name   = rtc_name,
+               .owner  = THIS_MODULE,
        },
 };
 
-static int __devinit vr41xx_rtc_init(void)
+static int __init vr41xx_rtc_init(void)
 {
        int retval;
 
@@ -684,10 +685,20 @@ static int __devinit vr41xx_rtc_init(void)
                break;
        }
 
-       rtc_platform_device = platform_device_register_simple("RTC", -1,
-                             rtc_resource, ARRAY_SIZE(rtc_resource));
-       if (IS_ERR(rtc_platform_device))
-               return PTR_ERR(rtc_platform_device);
+       rtc_platform_device = platform_device_alloc("RTC", -1);
+       if (!rtc_platform_device)
+               return -ENOMEM;
+
+       retval = platform_device_add_resources(rtc_platform_device,
+                               rtc_resource, ARRAY_SIZE(rtc_resource));
+
+       if (retval == 0)
+               retval = platform_device_add(rtc_platform_device);
+
+       if (retval < 0) {
+               platform_device_put(rtc_platform_device);
+               return retval;
+       }
 
        retval = platform_driver_register(&rtc_device_driver);
        if (retval < 0)
@@ -696,10 +707,9 @@ static int __devinit vr41xx_rtc_init(void)
        return retval;
 }
 
-static void __devexit vr41xx_rtc_exit(void)
+static void __exit vr41xx_rtc_exit(void)
 {
        platform_driver_unregister(&rtc_device_driver);
-
        platform_device_unregister(rtc_platform_device);
 }
 
index 00d9ef04a3697dde00f1d2121c526c33f4ec0c5e..f1b9cf89f153ab727d357435437c0f6fc54dea73 100644 (file)
@@ -228,15 +228,25 @@ static int __init mv64x60_wdt_init(void)
 
        printk(KERN_INFO "MV64x60 watchdog driver\n");
 
-       mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,
-                                                         -1, NULL, 0);
-       if (IS_ERR(mv64x60_wdt_dev)) {
-               ret = PTR_ERR(mv64x60_wdt_dev);
+       mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1);
+       if (!mv64x60_wdt_dev) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = platform_device_add(mv64x60_wdt_dev);
+       if (ret) {
+               platform_device_put(mv64x60_wdt_dev);
                goto out;
        }
 
        ret = platform_driver_register(&mv64x60_wdt_driver);
-      out:
+       if (ret) {
+               platform_device_unregister(mv64x60_wdt_dev);
+               goto out;
+       }
+
+ out:
        return ret;
 }
 
index 4652512f7d1a928a6830b5d15d91f4c20bdfc59e..3a4e5c5b4e1fc9d0fb421f9ed3cedd38a5f1fa26 100644 (file)
@@ -530,30 +530,27 @@ static DCDBAS_DEV_ATTR_RW(host_control_action);
 static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
 static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
 
-static struct device_attribute *dcdbas_dev_attrs[] = {
-       &dev_attr_smi_data_buf_size,
-       &dev_attr_smi_data_buf_phys_addr,
-       &dev_attr_smi_request,
-       &dev_attr_host_control_action,
-       &dev_attr_host_control_smi_type,
-       &dev_attr_host_control_on_shutdown,
+static struct attribute *dcdbas_dev_attrs[] = {
+       &dev_attr_smi_data_buf_size.attr,
+       &dev_attr_smi_data_buf_phys_addr.attr,
+       &dev_attr_smi_request.attr,
+       &dev_attr_host_control_action.attr,
+       &dev_attr_host_control_smi_type.attr,
+       &dev_attr_host_control_on_shutdown.attr,
        NULL
 };
 
-/**
- * dcdbas_init: initialize driver
- */
-static int __init dcdbas_init(void)
+static struct attribute_group dcdbas_attr_group = {
+       .attrs = dcdbas_dev_attrs,
+};
+
+static int __devinit dcdbas_probe(struct platform_device *dev)
 {
-       int i;
+       int i, error;
 
        host_control_action = HC_ACTION_NONE;
        host_control_smi_type = HC_SMITYPE_NONE;
 
-       dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-       if (IS_ERR(dcdbas_pdev))
-               return PTR_ERR(dcdbas_pdev);
-
        /*
         * BIOS SMI calls require buffer addresses be in 32-bit address space.
         * This is done by setting the DMA mask below.
@@ -561,19 +558,79 @@ static int __init dcdbas_init(void)
        dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
        dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;
 
+       error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
+       if (error)
+               return error;
+
+       for (i = 0; dcdbas_bin_attrs[i]; i++) {
+               error = sysfs_create_bin_file(&dev->dev.kobj,
+                                             dcdbas_bin_attrs[i]);
+               if (error) {
+                       while (--i >= 0)
+                               sysfs_remove_bin_file(&dev->dev.kobj,
+                                                     dcdbas_bin_attrs[i]);
+                       sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
+                       return error;
+               }
+       }
+
        register_reboot_notifier(&dcdbas_reboot_nb);
 
+       dev_info(&dev->dev, "%s (version %s)\n",
+                DRIVER_DESCRIPTION, DRIVER_VERSION);
+
+       return 0;
+}
+
+static int __devexit dcdbas_remove(struct platform_device *dev)
+{
+       int i;
+
+       unregister_reboot_notifier(&dcdbas_reboot_nb);
        for (i = 0; dcdbas_bin_attrs[i]; i++)
-               sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
-                                     dcdbas_bin_attrs[i]);
+               sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]);
+       sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
 
-       for (i = 0; dcdbas_dev_attrs[i]; i++)
-               device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
+       return 0;
+}
 
-       dev_info(&dcdbas_pdev->dev, "%s (version %s)\n",
-                DRIVER_DESCRIPTION, DRIVER_VERSION);
+static struct platform_driver dcdbas_driver = {
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = dcdbas_probe,
+       .remove         = __devexit_p(dcdbas_remove),
+};
+
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
+{
+       int error;
+
+       error = platform_driver_register(&dcdbas_driver);
+       if (error)
+               return error;
+
+       dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1);
+       if (!dcdbas_pdev) {
+               error = -ENOMEM;
+               goto err_unregister_driver;
+       }
+
+       error = platform_device_add(dcdbas_pdev);
+       if (error)
+               goto err_free_device;
 
        return 0;
+
+ err_free_device:
+       platform_device_put(dcdbas_pdev);
+ err_unregister_driver:
+       platform_driver_unregister(&dcdbas_driver);
+       return error;
 }
 
 /**
@@ -588,6 +645,15 @@ static void __exit dcdbas_exit(void)
        unregister_reboot_notifier(&dcdbas_reboot_nb);
        smi_data_buf_free();
        platform_device_unregister(dcdbas_pdev);
+       platform_driver_unregister(&dcdbas_driver);
+
+       /*
+        * We have to free the buffer here instead of dcdbas_remove
+        * because only in module exit function we can be sure that
+        * all sysfs attributes belonging to this module have been
+        * released.
+        */
+       smi_data_buf_free();
 }
 
 module_init(dcdbas_init);
index 88d60202b9db409bcfcc48069ef7bc49547172af..26b08ee425c74d6b0ce9ecee09a5d817a1e51841 100644 (file)
@@ -533,30 +533,35 @@ static void __clone_and_map(struct clone_info *ci)
 
        } else {
                /*
-                * Create two copy bios to deal with io that has
-                * been split across a target.
+                * Handle a bvec that must be split between two or more targets.
                 */
                struct bio_vec *bv = bio->bi_io_vec + ci->idx;
+               sector_t remaining = to_sector(bv->bv_len);
+               unsigned int offset = 0;
 
-               clone = split_bvec(bio, ci->sector, ci->idx,
-                                  bv->bv_offset, max);
-               __map_bio(ti, clone, tio);
+               do {
+                       if (offset) {
+                               ti = dm_table_find_target(ci->map, ci->sector);
+                               max = max_io_len(ci->md, ci->sector, ti);
 
-               ci->sector += max;
-               ci->sector_count -= max;
-               ti = dm_table_find_target(ci->map, ci->sector);
-
-               len = to_sector(bv->bv_len) - max;
-               clone = split_bvec(bio, ci->sector, ci->idx,
-                                  bv->bv_offset + to_bytes(max), len);
-               tio = alloc_tio(ci->md);
-               tio->io = ci->io;
-               tio->ti = ti;
-               memset(&tio->info, 0, sizeof(tio->info));
-               __map_bio(ti, clone, tio);
+                               tio = alloc_tio(ci->md);
+                               tio->io = ci->io;
+                               tio->ti = ti;
+                               memset(&tio->info, 0, sizeof(tio->info));
+                       }
+
+                       len = min(remaining, max);
+
+                       clone = split_bvec(bio, ci->sector, ci->idx,
+                                          bv->bv_offset + offset, len);
+
+                       __map_bio(ti, clone, tio);
+
+                       ci->sector += len;
+                       ci->sector_count -= len;
+                       offset += to_bytes(len);
+               } while (remaining -= len);
 
-               ci->sector += len;
-               ci->sector_count -= len;
                ci->idx++;
        }
 }
index 9d197efb481d4a3f2f08cec1bda3f04882b0de83..d188e4c670b512f6667825a39117a14a6a843d08 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends
index 7754d1974b9e0ac63ab7642cc0209e9093cabbc2..4262c1da6d4a883d1fc761f39e06b5629570e2d0 100644 (file)
 #define MAX_DESCS_PER_SKB      1
 #endif
 
+/*
+ * The MV643XX HW requires 8-byte alignment.  However, when I/O
+ * is non-cache-coherent, we need to ensure that the I/O buffers
+ * we use don't share cache lines with other data.
+ */
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_NOT_COHERENT_CACHE)
+#define ETH_DMA_ALIGN          L1_CACHE_BYTES
+#else
+#define ETH_DMA_ALIGN          8
+#endif
+
 #define ETH_VLAN_HLEN          4
 #define ETH_FCS_LEN            4
-#define ETH_DMA_ALIGN          8       /* hw requires 8-byte alignment */
-#define ETH_HW_IP_ALIGN                2       /* hw aligns IP header */
+#define ETH_HW_IP_ALIGN                2               /* hw aligns IP header */
 #define ETH_WRAPPER_LEN                (ETH_HW_IP_ALIGN + ETH_HLEN + \
-                               ETH_VLAN_HLEN + ETH_FCS_LEN)
-#define ETH_RX_SKB_SIZE                ((dev->mtu + ETH_WRAPPER_LEN + 7) & ~0x7)
+                                       ETH_VLAN_HLEN + ETH_FCS_LEN)
+#define ETH_RX_SKB_SIZE                (dev->mtu + ETH_WRAPPER_LEN + ETH_DMA_ALIGN)
 
 #define ETH_RX_QUEUES_ENABLED  (1 << 0)        /* use only Q0 for receive */
 #define ETH_TX_QUEUES_ENABLED  (1 << 0)        /* use only Q0 for transmit */
index 7e900572eaf83f93168fa91eb27b346fb69d5829..9595f74da93f46d893d3b3e2950c0909c344443e 100644 (file)
  *************************************************************************/
 
 #define DRV_NAME       "pcnet32"
-#define DRV_VERSION    "1.31c"
-#define DRV_RELDATE    "01.Nov.2005"
+#define DRV_VERSION    "1.32"
+#define DRV_RELDATE    "18.Mar.2006"
 #define PFX            DRV_NAME ": "
 
-static const char * const version =
-DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
+static const char *const version =
+    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -58,18 +58,23 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
  * PCI device identifiers for "new style" Linux PCI Device Drivers
  */
 static struct pci_device_id pcnet32_pci_tbl[] = {
-    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-    /*
-     * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
-     * the incorrect vendor id.
-     */
-    { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID,
-           PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0 },
-    { 0, }
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+       /*
+        * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
+        * the incorrect vendor id.
+        */
+       { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE,
+         PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
+
+       { }     /* terminate list */
 };
 
-MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl);
+MODULE_DEVICE_TABLE(pci, pcnet32_pci_tbl);
 
 static int cards_found;
 
@@ -77,13 +82,11 @@ static int cards_found;
  * VLB I/O addresses
  */
 static unsigned int pcnet32_portlist[] __initdata =
-       { 0x300, 0x320, 0x340, 0x360, 0 };
-
-
+    { 0x300, 0x320, 0x340, 0x360, 0 };
 
 static int pcnet32_debug = 0;
-static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
-static int pcnet32vlb;  /* check for VLB cards ? */
+static int tx_start = 1;       /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
+static int pcnet32vlb;         /* check for VLB cards ? */
 
 static struct net_device *pcnet32_dev;
 
@@ -110,32 +113,34 @@ static int rx_copybreak = 200;
  * to internal options
  */
 static const unsigned char options_mapping[] = {
-    PCNET32_PORT_ASEL,                    /*  0 Auto-select      */
-    PCNET32_PORT_AUI,                     /*  1 BNC/AUI          */
-    PCNET32_PORT_AUI,                     /*  2 AUI/BNC          */
-    PCNET32_PORT_ASEL,                    /*  3 not supported    */
-    PCNET32_PORT_10BT | PCNET32_PORT_FD,   /*  4 10baseT-FD      */
-    PCNET32_PORT_ASEL,                    /*  5 not supported    */
-    PCNET32_PORT_ASEL,                    /*  6 not supported    */
-    PCNET32_PORT_ASEL,                    /*  7 not supported    */
-    PCNET32_PORT_ASEL,                    /*  8 not supported    */
-    PCNET32_PORT_MII,                     /*  9 MII 10baseT      */
-    PCNET32_PORT_MII | PCNET32_PORT_FD,           /* 10 MII 10baseT-FD   */
-    PCNET32_PORT_MII,                     /* 11 MII (autosel)    */
-    PCNET32_PORT_10BT,                    /* 12 10BaseT          */
-    PCNET32_PORT_MII | PCNET32_PORT_100,   /* 13 MII 100BaseTx   */
-    PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, /* 14 MII 100BaseTx-FD */
-    PCNET32_PORT_ASEL                     /* 15 not supported    */
+       PCNET32_PORT_ASEL,                      /*  0 Auto-select      */
+       PCNET32_PORT_AUI,                       /*  1 BNC/AUI          */
+       PCNET32_PORT_AUI,                       /*  2 AUI/BNC          */
+       PCNET32_PORT_ASEL,                      /*  3 not supported    */
+       PCNET32_PORT_10BT | PCNET32_PORT_FD,    /*  4 10baseT-FD       */
+       PCNET32_PORT_ASEL,                      /*  5 not supported    */
+       PCNET32_PORT_ASEL,                      /*  6 not supported    */
+       PCNET32_PORT_ASEL,                      /*  7 not supported    */
+       PCNET32_PORT_ASEL,                      /*  8 not supported    */
+       PCNET32_PORT_MII,                       /*  9 MII 10baseT      */
+       PCNET32_PORT_MII | PCNET32_PORT_FD,     /* 10 MII 10baseT-FD   */
+       PCNET32_PORT_MII,                       /* 11 MII (autosel)    */
+       PCNET32_PORT_10BT,                      /* 12 10BaseT          */
+       PCNET32_PORT_MII | PCNET32_PORT_100,    /* 13 MII 100BaseTx    */
+                                               /* 14 MII 100BaseTx-FD */
+       PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD,
+       PCNET32_PORT_ASEL                       /* 15 not supported    */
 };
 
 static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
-    "Loopback test  (offline)"
+       "Loopback test  (offline)"
 };
+
 #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
 
-#define PCNET32_NUM_REGS 168
+#define PCNET32_NUM_REGS 136
 
-#define MAX_UNITS 8    /* More are supported, limit only on options */
+#define MAX_UNITS 8            /* More are supported, limit only on options */
 static int options[MAX_UNITS];
 static int full_duplex[MAX_UNITS];
 static int homepna[MAX_UNITS];
@@ -150,124 +155,6 @@ static int homepna[MAX_UNITS];
  * 16MB limitation and we don't need bounce buffers.
  */
 
-/*
- * History:
- * v0.01:  Initial version
- *        only tested on Alpha Noname Board
- * v0.02:  changed IRQ handling for new interrupt scheme (dev_id)
- *        tested on a ASUS SP3G
- * v0.10:  fixed an odd problem with the 79C974 in a Compaq Deskpro XL
- *        looks like the 974 doesn't like stopping and restarting in a
- *        short period of time; now we do a reinit of the lance; the
- *        bug was triggered by doing ifconfig eth0 <ip> broadcast <addr>
- *        and hangs the machine (thanks to Klaus Liedl for debugging)
- * v0.12:  by suggestion from Donald Becker: Renamed driver to pcnet32,
- *        made it standalone (no need for lance.c)
- * v0.13:  added additional PCI detecting for special PCI devices (Compaq)
- * v0.14:  stripped down additional PCI probe (thanks to David C Niemi
- *        and sveneric@xs4all.nl for testing this on their Compaq boxes)
- * v0.15:  added 79C965 (VLB) probe
- *        added interrupt sharing for PCI chips
- * v0.16:  fixed set_multicast_list on Alpha machines
- * v0.17:  removed hack from dev.c; now pcnet32 uses ethif_probe in Space.c
- * v0.19:  changed setting of autoselect bit
- * v0.20:  removed additional Compaq PCI probe; there is now a working one
- *        in arch/i386/bios32.c
- * v0.21:  added endian conversion for ppc, from work by cort@cs.nmt.edu
- * v0.22:  added printing of status to ring dump
- * v0.23:  changed enet_statistics to net_devive_stats
- * v0.90:  added multicast filter
- *        added module support
- *        changed irq probe to new style
- *        added PCnetFast chip id
- *        added fix for receive stalls with Intel saturn chipsets
- *        added in-place rx skbs like in the tulip driver
- *        minor cleanups
- * v0.91:  added PCnetFast+ chip id
- *        back port to 2.0.x
- * v1.00:  added some stuff from Donald Becker's 2.0.34 version
- *        added support for byte counters in net_dev_stats
- * v1.01:  do ring dumps, only when debugging the driver
- *        increased the transmit timeout
- * v1.02:  fixed memory leak in pcnet32_init_ring()
- * v1.10:  workaround for stopped transmitter
- *        added port selection for modules
- *        detect special T1/E1 WAN card and setup port selection
- * v1.11:  fixed wrong checking of Tx errors
- * v1.20:  added check of return value kmalloc (cpeterso@cs.washington.edu)
- *        added save original kmalloc addr for freeing (mcr@solidum.com)
- *        added support for PCnetHome chip (joe@MIT.EDU)
- *        rewritten PCI card detection
- *        added dwio mode to get driver working on some PPC machines
- * v1.21:  added mii selection and mii ioctl
- * v1.22:  changed pci scanning code to make PPC people happy
- *        fixed switching to 32bit mode in pcnet32_open() (thanks
- *        to Michael Richard <mcr@solidum.com> for noticing this one)
- *        added sub vendor/device id matching (thanks again to
- *        Michael Richard <mcr@solidum.com>)
- *        added chip id for 79c973/975 (thanks to Zach Brown <zab@zabbo.net>)
- * v1.23   fixed small bug, when manual selecting MII speed/duplex
- * v1.24   Applied Thomas' patch to use TxStartPoint and thus decrease TxFIFO
- *        underflows.  Added tx_start_pt module parameter. Increased
- *        TX_RING_SIZE from 16 to 32.  Added #ifdef'd code to use DXSUFLO
- *        for FAST[+] chipsets. <kaf@fc.hp.com>
- * v1.24ac Added SMP spinlocking - Alan Cox <alan@redhat.com>
- * v1.25kf Added No Interrupt on successful Tx for some Tx's <kaf@fc.hp.com>
- * v1.26   Converted to pci_alloc_consistent, Jamey Hicks / George France
- *                                           <jamey@crl.dec.com>
- * -      Fixed a few bugs, related to running the controller in 32bit mode.
- *        23 Oct, 2000.  Carsten Langgaard, carstenl@mips.com
- *        Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- * v1.26p  Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker
- * v1.27   improved CSR/PROM address detection, lots of cleanups,
- *        new pcnet32vlb module option, HP-PARISC support,
- *        added module parameter descriptions,
- *        initial ethtool support - Helge Deller <deller@gmx.de>
- * v1.27a  Sun Feb 10 2002 Go Taniguchi <go@turbolinux.co.jp>
- *        use alloc_etherdev and register_netdev
- *        fix pci probe not increment cards_found
- *        FD auto negotiate error workaround for xSeries250
- *        clean up and using new mii module
- * v1.27b  Sep 30 2002 Kent Yoder <yoder1@us.ibm.com>
- *        Added timer for cable connection state changes.
- * v1.28   20 Feb 2004 Don Fry <brazilnut@us.ibm.com>
- *        Jon Mason <jonmason@us.ibm.com>, Chinmay Albal <albal@in.ibm.com>
- *        Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl.
- *        Fixes bogus 'Bus master arbitration failure', pci_[un]map_single
- *        length errors, and transmit hangs.  Cleans up after errors in open.
- *        Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
- *        Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
- * v1.29   6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
- *        identification code (blink led's) and register dump.
- *        Don Fry added timer for 971/972 so skbufs don't remain on tx ring
- *        forever.
- * v1.30   18 May 2004 Don Fry removed timer and Last Transmit Interrupt
- *        (ltint) as they added complexity and didn't give good throughput.
- * v1.30a  22 May 2004 Don Fry limit frames received during interrupt.
- * v1.30b  24 May 2004 Don Fry fix bogus tx carrier errors with 79c973,
- *        assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>.
- * v1.30c  25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart.
- * v1.30d  01 Jun 2004 Don Fry discard oversize rx packets.
- * v1.30e  11 Jun 2004 Don Fry recover after fifo error and rx hang.
- * v1.30f  16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI,
- *        expanding on suggestions from Ralf Baechle <ralf@linux-mips.org>,
- *        and Brian Murphy <brian@murphy.dk>.
- * v1.30g  22 Jun 2004 Patrick Simmons <psimmons@flash.net> added option
- *        homepna for selecting HomePNA mode for PCNet/Home 79C978.
- * v1.30h  24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
- * v1.30i  28 Jun 2004 Don Fry change to use module_param.
- * v1.30j  29 Apr 2005 Don Fry fix skb/map leak with loopback test.
- * v1.31   02 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> added set_ringparam().
- * v1.31a  12 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> set min ring size to 4
- *        to allow loopback test to work unchanged.
- * v1.31b  06 Oct 2005 Don Fry changed alloc_ring to show name of device
- *        if allocation fails
- * v1.31c  01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only.
- *        Force 100Mbit FD if Auto (ASEL) is selected.
- *        See Bugzilla 2669 and 4551.
- */
-
-
 /*
  * Set the number of Tx and Rx buffers, using Log_2(# buffers).
  * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
@@ -303,42 +190,42 @@ static int homepna[MAX_UNITS];
 
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
-    u32 base;
-    s16 buf_length;
-    s16 status;
-    u32 msg_length;
-    u32 reserved;
+       u32     base;
+       s16     buf_length;
+       s16     status;
+       u32     msg_length;
+       u32     reserved;
 };
 
 struct pcnet32_tx_head {
-    u32 base;
-    s16 length;
-    s16 status;
-    u32 misc;
-    u32 reserved;
+       u32     base;
+       s16     length;
+       s16     status;
+       u32     misc;
+       u32     reserved;
 };
 
 /* The PCNET32 32-Bit initialization block, described in databook. */
 struct pcnet32_init_block {
-    u16 mode;
-    u16 tlen_rlen;
-    u8 phys_addr[6];
-    u16 reserved;
-    u32 filter[2];
-    /* Receive and transmit ring base, along with extra bits. */
-    u32 rx_ring;
-    u32 tx_ring;
+       u16     mode;
+       u16     tlen_rlen;
+       u8      phys_addr[6];
+       u16     reserved;
+       u32     filter[2];
+       /* Receive and transmit ring base, along with extra bits. */
+       u32     rx_ring;
+       u32     tx_ring;
 };
 
 /* PCnet32 access functions */
 struct pcnet32_access {
-    u16 (*read_csr)(unsigned long, int);
-    void (*write_csr)(unsigned long, int, u16);
-    u16 (*read_bcr)(unsigned long, int);
-    void (*write_bcr)(unsigned long, int, u16);
-    u16 (*read_rap)(unsigned long);
-    void (*write_rap)(unsigned long, u16);
-    void (*reset)(unsigned long);
+       u16     (*read_csr) (unsigned long, int);
+       void    (*write_csr) (unsigned long, int, u16);
+       u16     (*read_bcr) (unsigned long, int);
+       void    (*write_bcr) (unsigned long, int, u16);
+       u16     (*read_rap) (unsigned long);
+       void    (*write_rap) (unsigned long, u16);
+       void    (*reset) (unsigned long);
 };
 
 /*
@@ -346,760 +233,794 @@ struct pcnet32_access {
  * so the structure should be allocated using pci_alloc_consistent().
  */
 struct pcnet32_private {
-    struct pcnet32_init_block init_block;
-    /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
-    struct pcnet32_rx_head    *rx_ring;
-    struct pcnet32_tx_head    *tx_ring;
-    dma_addr_t         dma_addr;       /* DMA address of beginning of this
-                                          object, returned by
-                                          pci_alloc_consistent */
-    struct pci_dev     *pci_dev;       /* Pointer to the associated pci device
-                                          structure */
-    const char         *name;
-    /* The saved address of a sent-in-place packet/buffer, for skfree(). */
-    struct sk_buff     **tx_skbuff;
-    struct sk_buff     **rx_skbuff;
-    dma_addr_t         *tx_dma_addr;
-    dma_addr_t         *rx_dma_addr;
-    struct pcnet32_access      a;
-    spinlock_t         lock;           /* Guard lock */
-    unsigned int       cur_rx, cur_tx; /* The next free ring entry */
-    unsigned int       rx_ring_size;   /* current rx ring size */
-    unsigned int       tx_ring_size;   /* current tx ring size */
-    unsigned int       rx_mod_mask;    /* rx ring modular mask */
-    unsigned int       tx_mod_mask;    /* tx ring modular mask */
-    unsigned short     rx_len_bits;
-    unsigned short     tx_len_bits;
-    dma_addr_t         rx_ring_dma_addr;
-    dma_addr_t         tx_ring_dma_addr;
-    unsigned int       dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
-    struct net_device_stats stats;
-    char               tx_full;
-    int                        options;
-    unsigned int       shared_irq:1,   /* shared irq possible */
-                       dxsuflo:1,      /* disable transmit stop on uflo */
-                       mii:1;          /* mii port available */
-    struct net_device  *next;
-    struct mii_if_info mii_if;
-    struct timer_list  watchdog_timer;
-    struct timer_list  blink_timer;
-    u32                        msg_enable;     /* debug message level */
+       struct pcnet32_init_block init_block;
+       /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
+       struct pcnet32_rx_head  *rx_ring;
+       struct pcnet32_tx_head  *tx_ring;
+       dma_addr_t              dma_addr;/* DMA address of beginning of this
+                                  object, returned by pci_alloc_consistent */
+       struct pci_dev          *pci_dev;
+       const char              *name;
+       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       struct sk_buff          **tx_skbuff;
+       struct sk_buff          **rx_skbuff;
+       dma_addr_t              *tx_dma_addr;
+       dma_addr_t              *rx_dma_addr;
+       struct pcnet32_access   a;
+       spinlock_t              lock;           /* Guard lock */
+       unsigned int            cur_rx, cur_tx; /* The next free ring entry */
+       unsigned int            rx_ring_size;   /* current rx ring size */
+       unsigned int            tx_ring_size;   /* current tx ring size */
+       unsigned int            rx_mod_mask;    /* rx ring modular mask */
+       unsigned int            tx_mod_mask;    /* tx ring modular mask */
+       unsigned short          rx_len_bits;
+       unsigned short          tx_len_bits;
+       dma_addr_t              rx_ring_dma_addr;
+       dma_addr_t              tx_ring_dma_addr;
+       unsigned int            dirty_rx,       /* ring entries to be freed. */
+                               dirty_tx;
+
+       struct net_device_stats stats;
+       char                    tx_full;
+       char                    phycount;       /* number of phys found */
+       int                     options;
+       unsigned int            shared_irq:1,   /* shared irq possible */
+                               dxsuflo:1,   /* disable transmit stop on uflo */
+                               mii:1;          /* mii port available */
+       struct net_device       *next;
+       struct mii_if_info      mii_if;
+       struct timer_list       watchdog_timer;
+       struct timer_list       blink_timer;
+       u32                     msg_enable;     /* debug message level */
+
+       /* each bit indicates an available PHY */
+       u32                     phymask;
 };
 
 static void pcnet32_probe_vlbus(void);
-static int  pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
-static int  pcnet32_probe1(unsigned long, int, struct pci_dev *);
-static int  pcnet32_open(struct net_device *);
-static int  pcnet32_init_ring(struct net_device *);
-static int  pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int  pcnet32_rx(struct net_device *);
-static void pcnet32_tx_timeout (struct net_device *dev);
+static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
+static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
+static int pcnet32_open(struct net_device *);
+static int pcnet32_init_ring(struct net_device *);
+static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
+static int pcnet32_rx(struct net_device *);
+static void pcnet32_tx_timeout(struct net_device *dev);
 static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
-static int  pcnet32_close(struct net_device *);
+static int pcnet32_close(struct net_device *);
 static struct net_device_stats *pcnet32_get_stats(struct net_device *);
 static void pcnet32_load_multicast(struct net_device *dev);
 static void pcnet32_set_multicast_list(struct net_device *);
-static int  pcnet32_ioctl(struct net_device *, struct ifreq *, int);
+static int pcnet32_ioctl(struct net_device *, struct ifreq *, int);
 static void pcnet32_watchdog(struct net_device *);
 static int mdio_read(struct net_device *dev, int phy_id, int reg_num);
-static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val);
+static void mdio_write(struct net_device *dev, int phy_id, int reg_num,
+                      int val);
 static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
 static void pcnet32_ethtool_test(struct net_device *dev,
-       struct ethtool_test *eth_test, u64 *data);
-static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
+                                struct ethtool_test *eth_test, u64 * data);
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1);
 static int pcnet32_phys_id(struct net_device *dev, u32 data);
 static void pcnet32_led_blink_callback(struct net_device *dev);
 static int pcnet32_get_regs_len(struct net_device *dev);
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
-       void *ptr);
+                            void *ptr);
 static void pcnet32_purge_tx_ring(struct net_device *dev);
 static int pcnet32_alloc_ring(struct net_device *dev, char *name);
 static void pcnet32_free_ring(struct net_device *dev);
-
+static void pcnet32_check_media(struct net_device *dev, int verbose);
 
 enum pci_flags_bit {
-    PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-    PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+       PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
+       PCI_ADDR0 = 0x10 << 0, PCI_ADDR1 = 0x10 << 1, PCI_ADDR2 =
+           0x10 << 2, PCI_ADDR3 = 0x10 << 3,
 };
 
-
-static u16 pcnet32_wio_read_csr (unsigned long addr, int index)
+static u16 pcnet32_wio_read_csr(unsigned long addr, int index)
 {
-    outw (index, addr+PCNET32_WIO_RAP);
-    return inw (addr+PCNET32_WIO_RDP);
+       outw(index, addr + PCNET32_WIO_RAP);
+       return inw(addr + PCNET32_WIO_RDP);
 }
 
-static void pcnet32_wio_write_csr (unsigned long addr, int index, u16 val)
+static void pcnet32_wio_write_csr(unsigned long addr, int index, u16 val)
 {
-    outw (index, addr+PCNET32_WIO_RAP);
-    outw (val, addr+PCNET32_WIO_RDP);
+       outw(index, addr + PCNET32_WIO_RAP);
+       outw(val, addr + PCNET32_WIO_RDP);
 }
 
-static u16 pcnet32_wio_read_bcr (unsigned long addr, int index)
+static u16 pcnet32_wio_read_bcr(unsigned long addr, int index)
 {
-    outw (index, addr+PCNET32_WIO_RAP);
-    return inw (addr+PCNET32_WIO_BDP);
+       outw(index, addr + PCNET32_WIO_RAP);
+       return inw(addr + PCNET32_WIO_BDP);
 }
 
-static void pcnet32_wio_write_bcr (unsigned long addr, int index, u16 val)
+static void pcnet32_wio_write_bcr(unsigned long addr, int index, u16 val)
 {
-    outw (index, addr+PCNET32_WIO_RAP);
-    outw (val, addr+PCNET32_WIO_BDP);
+       outw(index, addr + PCNET32_WIO_RAP);
+       outw(val, addr + PCNET32_WIO_BDP);
 }
 
-static u16 pcnet32_wio_read_rap (unsigned long addr)
+static u16 pcnet32_wio_read_rap(unsigned long addr)
 {
-    return inw (addr+PCNET32_WIO_RAP);
+       return inw(addr + PCNET32_WIO_RAP);
 }
 
-static void pcnet32_wio_write_rap (unsigned long addr, u16 val)
+static void pcnet32_wio_write_rap(unsigned long addr, u16 val)
 {
-    outw (val, addr+PCNET32_WIO_RAP);
+       outw(val, addr + PCNET32_WIO_RAP);
 }
 
-static void pcnet32_wio_reset (unsigned long addr)
+static void pcnet32_wio_reset(unsigned long addr)
 {
-    inw (addr+PCNET32_WIO_RESET);
+       inw(addr + PCNET32_WIO_RESET);
 }
 
-static int pcnet32_wio_check (unsigned long addr)
+static int pcnet32_wio_check(unsigned long addr)
 {
-    outw (88, addr+PCNET32_WIO_RAP);
-    return (inw (addr+PCNET32_WIO_RAP) == 88);
+       outw(88, addr + PCNET32_WIO_RAP);
+       return (inw(addr + PCNET32_WIO_RAP) == 88);
 }
 
 static struct pcnet32_access pcnet32_wio = {
-    .read_csr  = pcnet32_wio_read_csr,
-    .write_csr = pcnet32_wio_write_csr,
-    .read_bcr  = pcnet32_wio_read_bcr,
-    .write_bcr = pcnet32_wio_write_bcr,
-    .read_rap  = pcnet32_wio_read_rap,
-    .write_rap = pcnet32_wio_write_rap,
-    .reset     = pcnet32_wio_reset
+       .read_csr = pcnet32_wio_read_csr,
+       .write_csr = pcnet32_wio_write_csr,
+       .read_bcr = pcnet32_wio_read_bcr,
+       .write_bcr = pcnet32_wio_write_bcr,
+       .read_rap = pcnet32_wio_read_rap,
+       .write_rap = pcnet32_wio_write_rap,
+       .reset = pcnet32_wio_reset
 };
 
-static u16 pcnet32_dwio_read_csr (unsigned long addr, int index)
+static u16 pcnet32_dwio_read_csr(unsigned long addr, int index)
 {
-    outl (index, addr+PCNET32_DWIO_RAP);
-    return (inl (addr+PCNET32_DWIO_RDP) & 0xffff);
+       outl(index, addr + PCNET32_DWIO_RAP);
+       return (inl(addr + PCNET32_DWIO_RDP) & 0xffff);
 }
 
-static void pcnet32_dwio_write_csr (unsigned long addr, int index, u16 val)
+static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val)
 {
-    outl (index, addr+PCNET32_DWIO_RAP);
-    outl (val, addr+PCNET32_DWIO_RDP);
+       outl(index, addr + PCNET32_DWIO_RAP);
+       outl(val, addr + PCNET32_DWIO_RDP);
 }
 
-static u16 pcnet32_dwio_read_bcr (unsigned long addr, int index)
+static u16 pcnet32_dwio_read_bcr(unsigned long addr, int index)
 {
-    outl (index, addr+PCNET32_DWIO_RAP);
-    return (inl (addr+PCNET32_DWIO_BDP) & 0xffff);
+       outl(index, addr + PCNET32_DWIO_RAP);
+       return (inl(addr + PCNET32_DWIO_BDP) & 0xffff);
 }
 
-static void pcnet32_dwio_write_bcr (unsigned long addr, int index, u16 val)
+static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val)
 {
-    outl (index, addr+PCNET32_DWIO_RAP);
-    outl (val, addr+PCNET32_DWIO_BDP);
+       outl(index, addr + PCNET32_DWIO_RAP);
+       outl(val, addr + PCNET32_DWIO_BDP);
 }
 
-static u16 pcnet32_dwio_read_rap (unsigned long addr)
+static u16 pcnet32_dwio_read_rap(unsigned long addr)
 {
-    return (inl (addr+PCNET32_DWIO_RAP) & 0xffff);
+       return (inl(addr + PCNET32_DWIO_RAP) & 0xffff);
 }
 
-static void pcnet32_dwio_write_rap (unsigned long addr, u16 val)
+static void pcnet32_dwio_write_rap(unsigned long addr, u16 val)
 {
-    outl (val, addr+PCNET32_DWIO_RAP);
+       outl(val, addr + PCNET32_DWIO_RAP);
 }
 
-static void pcnet32_dwio_reset (unsigned long addr)
+static void pcnet32_dwio_reset(unsigned long addr)
 {
-    inl (addr+PCNET32_DWIO_RESET);
+       inl(addr + PCNET32_DWIO_RESET);
 }
 
-static int pcnet32_dwio_check (unsigned long addr)
+static int pcnet32_dwio_check(unsigned long addr)
 {
-    outl (88, addr+PCNET32_DWIO_RAP);
-    return ((inl (addr+PCNET32_DWIO_RAP) & 0xffff) == 88);
+       outl(88, addr + PCNET32_DWIO_RAP);
+       return ((inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88);
 }
 
 static struct pcnet32_access pcnet32_dwio = {
-    .read_csr  = pcnet32_dwio_read_csr,
-    .write_csr = pcnet32_dwio_write_csr,
-    .read_bcr  = pcnet32_dwio_read_bcr,
-    .write_bcr = pcnet32_dwio_write_bcr,
-    .read_rap  = pcnet32_dwio_read_rap,
-    .write_rap = pcnet32_dwio_write_rap,
-    .reset     = pcnet32_dwio_reset
+       .read_csr = pcnet32_dwio_read_csr,
+       .write_csr = pcnet32_dwio_write_csr,
+       .read_bcr = pcnet32_dwio_read_bcr,
+       .write_bcr = pcnet32_dwio_write_bcr,
+       .read_rap = pcnet32_dwio_read_rap,
+       .write_rap = pcnet32_dwio_write_rap,
+       .reset = pcnet32_dwio_reset
 };
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void pcnet32_poll_controller(struct net_device *dev)
 {
-    disable_irq(dev->irq);
-    pcnet32_interrupt(0, dev, NULL);
-    enable_irq(dev->irq);
+       disable_irq(dev->irq);
+       pcnet32_interrupt(0, dev, NULL);
+       enable_irq(dev->irq);
 }
 #endif
 
-
 static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-    struct pcnet32_private *lp = dev->priv;
-    unsigned long flags;
-    int r = -EOPNOTSUPP;
-
-    if (lp->mii) {
-       spin_lock_irqsave(&lp->lock, flags);
-       mii_ethtool_gset(&lp->mii_if, cmd);
-       spin_unlock_irqrestore(&lp->lock, flags);
-       r = 0;
-    }
-    return r;
+       struct pcnet32_private *lp = dev->priv;
+       unsigned long flags;
+       int r = -EOPNOTSUPP;
+
+       if (lp->mii) {
+               spin_lock_irqsave(&lp->lock, flags);
+               mii_ethtool_gset(&lp->mii_if, cmd);
+               spin_unlock_irqrestore(&lp->lock, flags);
+               r = 0;
+       }
+       return r;
 }
 
 static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-    struct pcnet32_private *lp = dev->priv;
-    unsigned long flags;
-    int r = -EOPNOTSUPP;
+       struct pcnet32_private *lp = dev->priv;
+       unsigned long flags;
+       int r = -EOPNOTSUPP;
 
-    if (lp->mii) {
-       spin_lock_irqsave(&lp->lock, flags);
-       r = mii_ethtool_sset(&lp->mii_if, cmd);
-       spin_unlock_irqrestore(&lp->lock, flags);
-    }
-    return r;
+       if (lp->mii) {
+               spin_lock_irqsave(&lp->lock, flags);
+               r = mii_ethtool_sset(&lp->mii_if, cmd);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+       return r;
 }
 
-static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void pcnet32_get_drvinfo(struct net_device *dev,
+                               struct ethtool_drvinfo *info)
 {
-    struct pcnet32_private *lp = dev->priv;
-
-    strcpy (info->driver, DRV_NAME);
-    strcpy (info->version, DRV_VERSION);
-    if (lp->pci_dev)
-       strcpy (info->bus_info, pci_name(lp->pci_dev));
-    else
-       sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
+       struct pcnet32_private *lp = dev->priv;
+
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       if (lp->pci_dev)
+               strcpy(info->bus_info, pci_name(lp->pci_dev));
+       else
+               sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
 }
 
 static u32 pcnet32_get_link(struct net_device *dev)
 {
-    struct pcnet32_private *lp = dev->priv;
-    unsigned long flags;
-    int r;
-
-    spin_lock_irqsave(&lp->lock, flags);
-    if (lp->mii) {
-       r = mii_link_ok(&lp->mii_if);
-    } else {
-       ulong ioaddr = dev->base_addr;  /* card base I/O address */
-       r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
-    }
-    spin_unlock_irqrestore(&lp->lock, flags);
+       struct pcnet32_private *lp = dev->priv;
+       unsigned long flags;
+       int r;
 
-    return r;
+       spin_lock_irqsave(&lp->lock, flags);
+       if (lp->mii) {
+               r = mii_link_ok(&lp->mii_if);
+       } else {
+               ulong ioaddr = dev->base_addr;  /* card base I/O address */
+               r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       return r;
 }
 
 static u32 pcnet32_get_msglevel(struct net_device *dev)
 {
-    struct pcnet32_private *lp = dev->priv;
-    return lp->msg_enable;
+       struct pcnet32_private *lp = dev->priv;
+       return lp->msg_enable;
 }
 
 static void pcnet32_set_msglevel(struct net_device *dev, u32 value)
 {
-    struct pcnet32_private *lp = dev->priv;
-    lp->msg_enable = value;
+       struct pcnet32_private *lp = dev->priv;
+       lp->msg_enable = value;
 }
 
 static int pcnet32_nway_reset(struct net_device *dev)
 {
-    struct pcnet32_private *lp = dev->priv;
-    unsigned long flags;
-    int r = -EOPNOTSUPP;
+       struct pcnet32_private *lp = dev->priv;
+       unsigned long flags;
+       int r = -EOPNOTSUPP;
 
-    if (lp->mii) {
-       spin_lock_irqsave(&lp->lock, flags);
-       r = mii_nway_restart(&lp->mii_if);
-       spin_unlock_irqrestore(&lp->lock, flags);
-    }
-    return r;
+       if (lp->mii) {
+               spin_lock_irqsave(&lp->lock, flags);
+               r = mii_nway_restart(&lp->mii_if);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+       return r;
 }
 
-static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+static void pcnet32_get_ringparam(struct net_device *dev,
+                                 struct ethtool_ringparam *ering)
 {
-    struct pcnet32_private *lp = dev->priv;
+       struct pcnet32_private *lp = dev->priv;
 
-    ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
-    ering->tx_pending = lp->tx_ring_size - 1;
-    ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
-    ering->rx_pending = lp->rx_ring_size - 1;
+       ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
+       ering->tx_pending = lp->tx_ring_size - 1;
+       ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
+       ering->rx_pending = lp->rx_ring_size - 1;
 }
 
-static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+static int pcnet32_set_ringparam(struct net_device *dev,
+                                struct ethtool_ringparam *ering)
 {
-    struct pcnet32_private *lp = dev->priv;
-    unsigned long flags;
-    int i;
-
-    if (ering->rx_mini_pending || ering->rx_jumbo_pending)
-       return -EINVAL;
-
-    if (netif_running(dev))
-       pcnet32_close(dev);
-
-    spin_lock_irqsave(&lp->lock, flags);
-    pcnet32_free_ring(dev);
-    lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
-    lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
-
-    /* set the minimum ring size to 4, to allow the loopback test to work
-     * unchanged.
-     */
-    for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
-       if (lp->tx_ring_size <= (1 << i))
-           break;
-    }
-    lp->tx_ring_size = (1 << i);
-    lp->tx_mod_mask = lp->tx_ring_size - 1;
-    lp->tx_len_bits = (i << 12);
-
-    for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
-       if (lp->rx_ring_size <= (1 << i))
-           break;
-    }
-    lp->rx_ring_size = (1 << i);
-    lp->rx_mod_mask = lp->rx_ring_size - 1;
-    lp->rx_len_bits = (i << 4);
-
-    if (pcnet32_alloc_ring(dev, dev->name)) {
+       struct pcnet32_private *lp = dev->priv;
+       unsigned long flags;
+       int i;
+
+       if (ering->rx_mini_pending || ering->rx_jumbo_pending)
+               return -EINVAL;
+
+       if (netif_running(dev))
+               pcnet32_close(dev);
+
+       spin_lock_irqsave(&lp->lock, flags);
        pcnet32_free_ring(dev);
-       spin_unlock_irqrestore(&lp->lock, flags);
-       return -ENOMEM;
-    }
+       lp->tx_ring_size =
+           min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
+       lp->rx_ring_size =
+           min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
+
+       /* set the minimum ring size to 4, to allow the loopback test to work
+        * unchanged.
+        */
+       for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
+               if (lp->tx_ring_size <= (1 << i))
+                       break;
+       }
+       lp->tx_ring_size = (1 << i);
+       lp->tx_mod_mask = lp->tx_ring_size - 1;
+       lp->tx_len_bits = (i << 12);
 
-    spin_unlock_irqrestore(&lp->lock, flags);
+       for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
+               if (lp->rx_ring_size <= (1 << i))
+                       break;
+       }
+       lp->rx_ring_size = (1 << i);
+       lp->rx_mod_mask = lp->rx_ring_size - 1;
+       lp->rx_len_bits = (i << 4);
+
+       if (pcnet32_alloc_ring(dev, dev->name)) {
+               pcnet32_free_ring(dev);
+               spin_unlock_irqrestore(&lp->lock, flags);
+               return -ENOMEM;
+       }
 
-    if (pcnet32_debug & NETIF_MSG_DRV)
-       printk(KERN_INFO PFX "%s: Ring Param Settings: RX: %d, TX: %d\n",
-              dev->name, lp->rx_ring_size, lp->tx_ring_size);
+       spin_unlock_irqrestore(&lp->lock, flags);
 
-    if (netif_running(dev))
-       pcnet32_open(dev);
+       if (pcnet32_debug & NETIF_MSG_DRV)
+               printk(KERN_INFO PFX
+                      "%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name,
+                      lp->rx_ring_size, lp->tx_ring_size);
 
-    return 0;
+       if (netif_running(dev))
+               pcnet32_open(dev);
+
+       return 0;
 }
 
-static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+static void pcnet32_get_strings(struct net_device *dev, u32 stringset,
+                               u8 * data)
 {
-    memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test));
+       memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test));
 }
 
 static int pcnet32_self_test_count(struct net_device *dev)
 {
-    return PCNET32_TEST_LEN;
+       return PCNET32_TEST_LEN;
 }
 
 static void pcnet32_ethtool_test(struct net_device *dev,
-       struct ethtool_test *test, u64 *data)
+                                struct ethtool_test *test, u64 * data)
 {
-    struct pcnet32_private *lp = dev->priv;
-    int rc;
-
-    if (test->flags == ETH_TEST_FL_OFFLINE) {
-       rc = pcnet32_loopback_test(dev, data);
-       if (rc) {
-           if (netif_msg_hw(lp))
-               printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name);
-           test->flags |= ETH_TEST_FL_FAILED;
+       struct pcnet32_private *lp = dev->priv;
+       int rc;
+
+       if (test->flags == ETH_TEST_FL_OFFLINE) {
+               rc = pcnet32_loopback_test(dev, data);
+               if (rc) {
+                       if (netif_msg_hw(lp))
+                               printk(KERN_DEBUG "%s: Loopback test failed.\n",
+                                      dev->name);
+                       test->flags |= ETH_TEST_FL_FAILED;
+               } else if (netif_msg_hw(lp))
+                       printk(KERN_DEBUG "%s: Loopback test passed.\n",
+                              dev->name);
        } else if (netif_msg_hw(lp))
-           printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name);
-    } else if (netif_msg_hw(lp))
-       printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).",            dev->name);
-} /* end pcnet32_ethtool_test */
+               printk(KERN_DEBUG
+                      "%s: No tests to run (specify 'Offline' on ethtool).",
+                      dev->name);
+}                              /* end pcnet32_ethtool_test */
 
-static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
 {
-    struct pcnet32_private *lp = dev->priv;
-    struct pcnet32_access *a = &lp->a; /* access to registers */
-    ulong ioaddr = dev->base_addr;     /* card base I/O address */
-    struct sk_buff *skb;               /* sk buff */
-    int x, i;                          /* counters */
-    int numbuffs = 4;                  /* number of TX/RX buffers and descs */
-    u16 status = 0x8300;               /* TX ring status */
-    u16 teststatus;                    /* test of ring status */
-    int rc;                            /* return code */
-    int size;                          /* size of packets */
-    unsigned char *packet;             /* source packet data */
-    static const int data_len = 60;            /* length of source packets */
-    unsigned long flags;
-    unsigned long ticks;
-
-    *data1 = 1;                        /* status of test, default to fail */
-    rc = 1;                    /* default to fail */
-
-    if (netif_running(dev))
-       pcnet32_close(dev);
-
-    spin_lock_irqsave(&lp->lock, flags);
-
-    /* Reset the PCNET32 */
-    lp->a.reset (ioaddr);
-
-    /* switch pcnet32 to 32bit mode */
-    lp->a.write_bcr (ioaddr, 20, 2);
-
-    lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
-    lp->init_block.filter[0] = 0;
-    lp->init_block.filter[1] = 0;
-
-    /* purge & init rings but don't actually restart */
-    pcnet32_restart(dev, 0x0000);
-
-    lp->a.write_csr(ioaddr, 0, 0x0004);        /* Set STOP bit */
-
-    /* Initialize Transmit buffers. */
-    size = data_len + 15;
-    for (x=0; x<numbuffs; x++) {
-       if (!(skb = dev_alloc_skb(size))) {
-           if (netif_msg_hw(lp))
-               printk(KERN_DEBUG "%s: Cannot allocate skb at line: %d!\n",
-                   dev->name, __LINE__);
-           goto clean_up;
-       } else {
-           packet = skb->data;
-           skb_put(skb, size);         /* create space for data */
-           lp->tx_skbuff[x] = skb;
-           lp->tx_ring[x].length = le16_to_cpu(-skb->len);
-           lp->tx_ring[x].misc = 0;
-
-            /* put DA and SA into the skb */
-           for (i=0; i<6; i++)
-               *packet++ = dev->dev_addr[i];
-           for (i=0; i<6; i++)
-               *packet++ = dev->dev_addr[i];
-           /* type */
-           *packet++ = 0x08;
-           *packet++ = 0x06;
-           /* packet number */
-           *packet++ = x;
-           /* fill packet with data */
-           for (i=0; i<data_len; i++)
-               *packet++ = i;
-
-           lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data,
-                   skb->len, PCI_DMA_TODEVICE);
-           lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]);
-           wmb(); /* Make sure owner changes after all others are visible */
-           lp->tx_ring[x].status = le16_to_cpu(status);
-       }
-    }
-
-    x = a->read_bcr(ioaddr, 32);       /* set internal loopback in BSR32 */
-    x = x | 0x0002;
-    a->write_bcr(ioaddr, 32, x);
-
-    lp->a.write_csr (ioaddr, 15, 0x0044);      /* set int loopback in CSR15 */
-
-    teststatus = le16_to_cpu(0x8000);
-    lp->a.write_csr(ioaddr, 0, 0x0002);                /* Set STRT bit */
-
-    /* Check status of descriptors */
-    for (x=0; x<numbuffs; x++) {
-       ticks = 0;
-       rmb();
-       while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
-           spin_unlock_irqrestore(&lp->lock, flags);
-           mdelay(1);
-           spin_lock_irqsave(&lp->lock, flags);
-           rmb();
-           ticks++;
-       }
-       if (ticks == 200) {
-           if (netif_msg_hw(lp))
-               printk("%s: Desc %d failed to reset!\n",dev->name,x);
-           break;
-       }
-    }
-
-    lp->a.write_csr(ioaddr, 0, 0x0004);                /* Set STOP bit */
-    wmb();
-    if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
-       printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
-
-       for (x=0; x<numbuffs; x++) {
-           printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);
-           skb = lp->rx_skbuff[x];
-           for (i=0; i<size; i++) {
-               printk("%02x ", *(skb->data+i));
-           }
-           printk("\n");
-       }
-    }
-
-    x = 0;
-    rc = 0;
-    while (x<numbuffs && !rc) {
-       skb = lp->rx_skbuff[x];
-       packet = lp->tx_skbuff[x]->data;
-       for (i=0; i<size; i++) {
-           if (*(skb->data+i) != packet[i]) {
-               if (netif_msg_hw(lp))
-                   printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n",
-                           dev->name, i, *(skb->data+i), packet[i]);
-               rc = 1;
-               break;
-           }
+       struct pcnet32_private *lp = dev->priv;
+       struct pcnet32_access *a = &lp->a;      /* access to registers */
+       ulong ioaddr = dev->base_addr;  /* card base I/O address */
+       struct sk_buff *skb;    /* sk buff */
+       int x, i;               /* counters */
+       int numbuffs = 4;       /* number of TX/RX buffers and descs */
+       u16 status = 0x8300;    /* TX ring status */
+       u16 teststatus;         /* test of ring status */
+       int rc;                 /* return code */
+       int size;               /* size of packets */
+       unsigned char *packet;  /* source packet data */
+       static const int data_len = 60; /* length of source packets */
+       unsigned long flags;
+       unsigned long ticks;
+
+       *data1 = 1;             /* status of test, default to fail */
+       rc = 1;                 /* default to fail */
+
+       if (netif_running(dev))
+               pcnet32_close(dev);
+
+       spin_lock_irqsave(&lp->lock, flags);
+
+       /* Reset the PCNET32 */
+       lp->a.reset(ioaddr);
+
+       /* switch pcnet32 to 32bit mode */
+       lp->a.write_bcr(ioaddr, 20, 2);
+
+       lp->init_block.mode =
+           le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
+       lp->init_block.filter[0] = 0;
+       lp->init_block.filter[1] = 0;
+
+       /* purge & init rings but don't actually restart */
+       pcnet32_restart(dev, 0x0000);
+
+       lp->a.write_csr(ioaddr, 0, 0x0004);     /* Set STOP bit */
+
+       /* Initialize Transmit buffers. */
+       size = data_len + 15;
+       for (x = 0; x < numbuffs; x++) {
+               if (!(skb = dev_alloc_skb(size))) {
+                       if (netif_msg_hw(lp))
+                               printk(KERN_DEBUG
+                                      "%s: Cannot allocate skb at line: %d!\n",
+                                      dev->name, __LINE__);
+                       goto clean_up;
+               } else {
+                       packet = skb->data;
+                       skb_put(skb, size);     /* create space for data */
+                       lp->tx_skbuff[x] = skb;
+                       lp->tx_ring[x].length = le16_to_cpu(-skb->len);
+                       lp->tx_ring[x].misc = 0;
+
+                       /* put DA and SA into the skb */
+                       for (i = 0; i < 6; i++)
+                               *packet++ = dev->dev_addr[i];
+                       for (i = 0; i < 6; i++)
+                               *packet++ = dev->dev_addr[i];
+                       /* type */
+                       *packet++ = 0x08;
+                       *packet++ = 0x06;
+                       /* packet number */
+                       *packet++ = x;
+                       /* fill packet with data */
+                       for (i = 0; i < data_len; i++)
+                               *packet++ = i;
+
+                       lp->tx_dma_addr[x] =
+                           pci_map_single(lp->pci_dev, skb->data, skb->len,
+                                          PCI_DMA_TODEVICE);
+                       lp->tx_ring[x].base =
+                           (u32) le32_to_cpu(lp->tx_dma_addr[x]);
+                       wmb();  /* Make sure owner changes after all others are visible */
+                       lp->tx_ring[x].status = le16_to_cpu(status);
+               }
+       }
+
+       x = a->read_bcr(ioaddr, 32);    /* set internal loopback in BSR32 */
+       x = x | 0x0002;
+       a->write_bcr(ioaddr, 32, x);
+
+       lp->a.write_csr(ioaddr, 15, 0x0044);    /* set int loopback in CSR15 */
+
+       teststatus = le16_to_cpu(0x8000);
+       lp->a.write_csr(ioaddr, 0, 0x0002);     /* Set STRT bit */
+
+       /* Check status of descriptors */
+       for (x = 0; x < numbuffs; x++) {
+               ticks = 0;
+               rmb();
+               while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
+                       spin_unlock_irqrestore(&lp->lock, flags);
+                       mdelay(1);
+                       spin_lock_irqsave(&lp->lock, flags);
+                       rmb();
+                       ticks++;
+               }
+               if (ticks == 200) {
+                       if (netif_msg_hw(lp))
+                               printk("%s: Desc %d failed to reset!\n",
+                                      dev->name, x);
+                       break;
+               }
+       }
+
+       lp->a.write_csr(ioaddr, 0, 0x0004);     /* Set STOP bit */
+       wmb();
+       if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
+               printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
+
+               for (x = 0; x < numbuffs; x++) {
+                       printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);
+                       skb = lp->rx_skbuff[x];
+                       for (i = 0; i < size; i++) {
+                               printk("%02x ", *(skb->data + i));
+                       }
+                       printk("\n");
+               }
+       }
+
+       x = 0;
+       rc = 0;
+       while (x < numbuffs && !rc) {
+               skb = lp->rx_skbuff[x];
+               packet = lp->tx_skbuff[x]->data;
+               for (i = 0; i < size; i++) {
+                       if (*(skb->data + i) != packet[i]) {
+                               if (netif_msg_hw(lp))
+                                       printk(KERN_DEBUG
+                                              "%s: Error in compare! %2x - %02x %02x\n",
+                                              dev->name, i, *(skb->data + i),
+                                              packet[i]);
+                               rc = 1;
+                               break;
+                       }
+               }
+               x++;
+       }
+       if (!rc) {
+               *data1 = 0;
        }
-       x++;
-    }
-    if (!rc) {
-       *data1 = 0;
-    }
 
-clean_up:
-    pcnet32_purge_tx_ring(dev);
-    x = a->read_csr(ioaddr, 15) & 0xFFFF;
-    a->write_csr(ioaddr, 15, (x & ~0x0044));   /* reset bits 6 and 2 */
+      clean_up:
+       pcnet32_purge_tx_ring(dev);
+       x = a->read_csr(ioaddr, 15) & 0xFFFF;
+       a->write_csr(ioaddr, 15, (x & ~0x0044));        /* reset bits 6 and 2 */
 
-    x = a->read_bcr(ioaddr, 32);               /* reset internal loopback */
-    x = x & ~0x0002;
-    a->write_bcr(ioaddr, 32, x);
+       x = a->read_bcr(ioaddr, 32);    /* reset internal loopback */
+       x = x & ~0x0002;
+       a->write_bcr(ioaddr, 32, x);
 
-    spin_unlock_irqrestore(&lp->lock, flags);
+       spin_unlock_irqrestore(&lp->lock, flags);
 
-    if (netif_running(dev)) {
-       pcnet32_open(dev);
-    } else {
-       lp->a.write_bcr (ioaddr, 20, 4);        /* return to 16bit mode */
-    }
+       if (netif_running(dev)) {
+               pcnet32_open(dev);
+       } else {
+               lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
+       }
 
-    return(rc);
-} /* end pcnet32_loopback_test  */
+       return (rc);
+}                              /* end pcnet32_loopback_test  */
 
 static void pcnet32_led_blink_callback(struct net_device *dev)
 {
-    struct pcnet32_private *lp = dev->priv;
-    struct pcnet32_access *a = &lp->a;
-    ulong ioaddr = dev->base_addr;
-    unsigned long flags;
-    int i;
-
-    spin_lock_irqsave(&lp->lock, flags);
-    for (i=4; i<8; i++) {
-       a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
-    }
-    spin_unlock_irqrestore(&lp->lock, flags);
-
-    mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT);
+       struct pcnet32_private *lp = dev->priv;
+       struct pcnet32_access *a = &lp->a;
+       ulong ioaddr = dev->base_addr;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&lp->lock, flags);
+       for (i = 4; i < 8; i++) {
+               a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT);
 }
 
 static int pcnet32_phys_id(struct net_device *dev, u32 data)
 {
-    struct pcnet32_private *lp = dev->priv;
-    struct pcnet32_access *a = &lp->a;
-    ulong ioaddr = dev->base_addr;
-    unsigned long flags;
-    int i, regs[4];
-
-    if (!lp->blink_timer.function) {
-       init_timer(&lp->blink_timer);
-       lp->blink_timer.function = (void *) pcnet32_led_blink_callback;
-       lp->blink_timer.data = (unsigned long) dev;
-    }
-
-    /* Save the current value of the bcrs */
-    spin_lock_irqsave(&lp->lock, flags);
-    for (i=4; i<8; i++) {
-       regs[i-4] = a->read_bcr(ioaddr, i);
-    }
-    spin_unlock_irqrestore(&lp->lock, flags);
-
-    mod_timer(&lp->blink_timer, jiffies);
-    set_current_state(TASK_INTERRUPTIBLE);
-
-    if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
-    data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
-    msleep_interruptible(data * 1000);
-    del_timer_sync(&lp->blink_timer);
-
-    /* Restore the original value of the bcrs */
-    spin_lock_irqsave(&lp->lock, flags);
-    for (i=4; i<8; i++) {
-       a->write_bcr(ioaddr, i, regs[i-4]);
-    }
-    spin_unlock_irqrestore(&lp->lock, flags);
-
-    return 0;
+       struct pcnet32_private *lp = dev->priv;
+       struct pcnet32_access *a = &lp->a;
+       ulong ioaddr = dev->base_addr;
+       unsigned long flags;
+       int i, regs[4];
+
+       if (!lp->blink_timer.function) {
+               init_timer(&lp->blink_timer);
+               lp->blink_timer.function = (void *)pcnet32_led_blink_callback;
+               lp->blink_timer.data = (unsigned long)dev;
+       }
+
+       /* Save the current value of the bcrs */
+       spin_lock_irqsave(&lp->lock, flags);
+       for (i = 4; i < 8; i++) {
+               regs[i - 4] = a->read_bcr(ioaddr, i);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       mod_timer(&lp->blink_timer, jiffies);
+       set_current_state(TASK_INTERRUPTIBLE);
+
+       if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ)))
+               data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ);
+
+       msleep_interruptible(data * 1000);
+       del_timer_sync(&lp->blink_timer);
+
+       /* Restore the original value of the bcrs */
+       spin_lock_irqsave(&lp->lock, flags);
+       for (i = 4; i < 8; i++) {
+               a->write_bcr(ioaddr, i, regs[i - 4]);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       return 0;
 }
 
+#define PCNET32_REGS_PER_PHY   32
+#define PCNET32_MAX_PHYS       32
 static int pcnet32_get_regs_len(struct net_device *dev)
 {
-    return(PCNET32_NUM_REGS * sizeof(u16));
+       struct pcnet32_private *lp = dev->priv;
+       int j = lp->phycount * PCNET32_REGS_PER_PHY;
+
+       return ((PCNET32_NUM_REGS + j) * sizeof(u16));
 }
 
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
-       void *ptr)
+                            void *ptr)
 {
-    int i, csr0;
-    u16 *buff = ptr;
-    struct pcnet32_private *lp = dev->priv;
-    struct pcnet32_access *a = &lp->a;
-    ulong ioaddr = dev->base_addr;
-    int ticks;
-    unsigned long flags;
-
-    spin_lock_irqsave(&lp->lock, flags);
-
-    csr0 = a->read_csr(ioaddr, 0);
-    if (!(csr0 & 0x0004)) {    /* If not stopped */
-       /* set SUSPEND (SPND) - CSR5 bit 0 */
-       a->write_csr(ioaddr, 5, 0x0001);
-
-       /* poll waiting for bit to be set */
-       ticks = 0;
-       while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
-           spin_unlock_irqrestore(&lp->lock, flags);
-           mdelay(1);
-           spin_lock_irqsave(&lp->lock, flags);
-           ticks++;
-           if (ticks > 200) {
-               if (netif_msg_hw(lp))
-                   printk(KERN_DEBUG "%s: Error getting into suspend!\n",
-                           dev->name);
-               break;
-           }
-       }
-    }
+       int i, csr0;
+       u16 *buff = ptr;
+       struct pcnet32_private *lp = dev->priv;
+       struct pcnet32_access *a = &lp->a;
+       ulong ioaddr = dev->base_addr;
+       int ticks;
+       unsigned long flags;
 
-    /* read address PROM */
-    for (i=0; i<16; i += 2)
-       *buff++ = inw(ioaddr + i);
+       spin_lock_irqsave(&lp->lock, flags);
 
-    /* read control and status registers */
-    for (i=0; i<90; i++) {
-       *buff++ = a->read_csr(ioaddr, i);
-    }
+       csr0 = a->read_csr(ioaddr, 0);
+       if (!(csr0 & 0x0004)) { /* If not stopped */
+               /*&