Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm

* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm: (44 commits)
  dm raid1: report fault status
  dm raid1: handle read failures
  dm raid1: fix EIO after log failure
  dm raid1: handle recovery failures
  dm raid1: handle write failures
  dm snapshot: combine consecutive exceptions in memory
  dm: stripe enhanced status return
  dm: stripe trigger event on failure
  dm log: auto load modules
  dm: move deferred bio flushing to workqueue
  dm crypt: use async crypto
  dm crypt: prepare async callback fn
  dm crypt: add completion for async
  dm crypt: add async request mempool
  dm crypt: extract scatterlist processing
  dm crypt: tidy io ref counting
  dm crypt: introduce crypt_write_io_loop
  dm crypt: abstract crypt_write_done
  dm crypt: store sector mapping in dm_crypt_io
  dm crypt: move queue functions
  ...
diff --git a/Documentation/DocBook/scsi.tmpl b/Documentation/DocBook/scsi.tmpl
index f299ab1..10a150a 100644
--- a/Documentation/DocBook/scsi.tmpl
+++ b/Documentation/DocBook/scsi.tmpl
@@ -12,7 +12,7 @@
         <surname>Bottomley</surname>
         <affiliation>
           <address>
-            <email>James.Bottomley@steeleye.com</email>
+            <email>James.Bottomley@hansenpartnership.com</email>
           </address>
         </affiliation>
       </author>
diff --git a/Documentation/hwmon/ads7828 b/Documentation/hwmon/ads7828
new file mode 100644
index 0000000..75bc4be
--- /dev/null
+++ b/Documentation/hwmon/ads7828
@@ -0,0 +1,36 @@
+Kernel driver ads7828
+=====================
+
+Supported chips:
+  * Texas Instruments/Burr-Brown ADS7828
+    Prefix: 'ads7828'
+    Addresses scanned: I2C 0x48, 0x49, 0x4a, 0x4b
+    Datasheet: Publicly available at the Texas Instruments website :
+               http://focus.ti.com/lit/ds/symlink/ads7828.pdf
+
+Authors:
+        Steve Hardy <steve@linuxrealtime.co.uk>
+
+Module Parameters
+-----------------
+
+* se_input: bool (default Y)
+  Single ended operation - set to N for differential mode
+* int_vref: bool (default Y)
+  Operate with the internal 2.5V reference - set to N for external reference
+* vref_mv: int (default 2500)
+  If using an external reference, set this to the reference voltage in mV
+
+Description
+-----------
+
+This driver implements support for the Texas Instruments ADS7828.
+
+This device is a 12-bit 8-channel A-D converter.
+
+It can operate in single ended mode (8 +ve inputs) or in differential mode,
+where 4 differential pairs can be measured.
+
+The chip also has the facility to use an external voltage reference.  This
+may be required if your hardware supplies the ADS7828 from a 5V supply, see
+the datasheet for more details.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 5b704a4..f4ce1fd 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -30,7 +30,7 @@
     Datasheet: No longer be available
 
 Authors:
-    Christophe Gauthron <chrisg@0-in.com>
+    Christophe Gauthron
     Jean Delvare <khali@linux-fr.org>
 
 
diff --git a/Documentation/hwmon/lm78 b/Documentation/hwmon/lm78
index dfc318a..60932e2 100644
--- a/Documentation/hwmon/lm78
+++ b/Documentation/hwmon/lm78
@@ -4,12 +4,12 @@
 Supported chips:
   * National Semiconductor LM78 / LM78-J
     Prefix: 'lm78'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports)
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
   * National Semiconductor LM79
     Prefix: 'lm79'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports)
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
 
diff --git a/Documentation/hwmon/lm87 b/Documentation/hwmon/lm87
index c952c57..ec27aa1 100644
--- a/Documentation/hwmon/lm87
+++ b/Documentation/hwmon/lm87
@@ -4,8 +4,12 @@
 Supported chips:
   * National Semiconductor LM87
     Prefix: 'lm87'
-    Addresses scanned: I2C 0x2c - 0x2f
+    Addresses scanned: I2C 0x2c - 0x2e
     Datasheet: http://www.national.com/pf/LM/LM87.html
+  * Analog Devices ADM1024
+    Prefix: 'adm1024'
+    Addresses scanned: I2C 0x2c - 0x2e
+    Datasheet: http://www.analog.com/en/prod/0,2877,ADM1024,00.html
 
 Authors:
         Frodo Looijaard <frodol@dds.nl>,
@@ -19,11 +23,12 @@
 Description
 -----------
 
-This driver implements support for the National Semiconductor LM87.
+This driver implements support for the National Semiconductor LM87
+and the Analog Devices ADM1024.
 
 The LM87 implements up to three temperature sensors, up to two fan
 rotation speed sensors, up to seven voltage sensors, alarms, and some
-miscellaneous stuff.
+miscellaneous stuff. The ADM1024 is fully compatible.
 
 Temperatures are measured in degrees Celsius. Each input has a high
 and low alarm settings. A high limit produces an alarm when the value
diff --git a/Documentation/hwmon/userspace-tools b/Documentation/hwmon/userspace-tools
index 19900a8..9865aee 100644
--- a/Documentation/hwmon/userspace-tools
+++ b/Documentation/hwmon/userspace-tools
@@ -14,7 +14,7 @@
 
 Core set of utilities that will allow you to obtain health information,
 setup monitoring limits etc. You can get them on their homepage
-http://www.lm-sensors.nu/ or as a package from your Linux distribution.
+http://www.lm-sensors.org/ or as a package from your Linux distribution.
 
 If from website:
 Get lm-sensors from project web site. Please note, you need only userspace
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index ccc2bcb..d6e1ae3 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -23,8 +23,9 @@
 
 The chips implement three temperature sensors, five fan rotation
 speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
-VID (6 pins), alarms with beep warnings (control unimplemented), and
-some automatic fan regulation strategies (plus manual fan control mode).
+VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG), alarms with beep
+warnings (control unimplemented), and some automatic fan regulation
+strategies (plus manual fan control mode).
 
 Temperatures are measured in degrees Celsius and measurement resolution is 1
 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
diff --git a/Documentation/hwmon/w83627hf b/Documentation/hwmon/w83627hf
index 7922319..880a59f 100644
--- a/Documentation/hwmon/w83627hf
+++ b/Documentation/hwmon/w83627hf
@@ -73,5 +73,4 @@
 
 For further information on this driver see the w83781d driver documentation.
 
-[1] http://www2.lm-sensors.nu/~lm78/cvs/browse.cgi/lm_sensors2/doc/vid
-
+[1] http://www.lm-sensors.org/browser/lm-sensors/trunk/doc/vid
diff --git a/Documentation/hwmon/w83781d b/Documentation/hwmon/w83781d
index b1e9f80..6f800a0 100644
--- a/Documentation/hwmon/w83781d
+++ b/Documentation/hwmon/w83781d
@@ -4,20 +4,16 @@
 Supported chips:
   * Winbond W83781D
     Prefix: 'w83781d'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports)
     Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83781d.pdf
   * Winbond W83782D
     Prefix: 'w83782d'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Addresses scanned: I2C 0x28 - 0x2f, ISA 0x290 (8 I/O ports)
     Datasheet: http://www.winbond.com/PDF/sheet/w83782d.pdf
   * Winbond W83783S
     Prefix: 'w83783s'
     Addresses scanned: I2C 0x2d
     Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83783s.pdf
-  * Winbond W83627HF
-    Prefix: 'w83627hf'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
-    Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
   * Asus AS99127F
     Prefix: 'as99127f'
     Addresses scanned: I2C 0x28 - 0x2f
@@ -50,20 +46,18 @@
 Description
 -----------
 
-This driver implements support for the Winbond W83781D, W83782D, W83783S,
-W83627HF chips, and the Asus AS99127F chips. We will refer to them
-collectively as W8378* chips.
+This driver implements support for the Winbond W83781D, W83782D, W83783S
+chips, and the Asus AS99127F chips. We will refer to them collectively as
+W8378* chips.
 
 There is quite some difference between these chips, but they are similar
 enough that it was sensible to put them together in one driver.
-The W83627HF chip is assumed to be identical to the ISA W83782D.
 The Asus chips are similar to an I2C-only W83782D.
 
 Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
 as99127f    7       3       0       3       0x31    0x12c3  yes     no
 as99127f rev.2 (type_name = as99127f)       0x31    0x5ca3  yes     no
 w83781d     7       3       0       3       0x10-1  0x5ca3  yes     yes
-w83627hf    9       3       2       3       0x21    0x5ca3  yes     yes(LPC)
 w83782d     9       3       2-4     3       0x30    0x5ca3  yes     yes
 w83783s     5-6     3       2       1-2     0x40    0x5ca3  yes     no
 
@@ -143,9 +137,9 @@
 0x000400: in6
 0x000800: fan3
 0x001000: chassis
-0x002000: temp3 (W83782D and W83627HF only)
-0x010000: in7 (W83782D and W83627HF only)
-0x020000: in8 (W83782D and W83627HF only)
+0x002000: temp3 (W83782D only)
+0x010000: in7 (W83782D only)
+0x020000: in8 (W83782D only)
 
 If an alarm triggers, it will remain triggered until the hardware register
 is read at least once. This means that the cause for the alarm may
diff --git a/Documentation/hwmon/w83l786ng b/Documentation/hwmon/w83l786ng
new file mode 100644
index 0000000..d8f55d7
--- /dev/null
+++ b/Documentation/hwmon/w83l786ng
@@ -0,0 +1,54 @@
+Kernel driver w83l786ng
+=====================
+
+Supported chips:
+  * Winbond W83L786NG/W83L786NR
+    Prefix: 'w83l786ng'
+    Addresses scanned: I2C 0x2e - 0x2f
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L786NRNG09.pdf
+
+Author: Kevin Lo <kevlo@kevlo.org>
+
+
+Module Parameters
+-----------------
+
+* reset boolean
+  (default 0)
+  Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default
+  behavior is no chip reset to preserve BIOS settings
+
+
+Description
+-----------
+
+This driver implements support for Winbond W83L786NG/W83L786NR chips.
+
+The driver implements two temperature sensors, two fan rotation speed
+sensors, and three voltage sensors.
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and temp2.
+
+Fan rotation speeds are reported in RPM (rotations per minute). Fan readings
+readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64
+or 128 for fan 1/2) to give the readings more range or accuracy.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+/sys files
+----------
+
+pwm[1-2] - this file stores PWM duty cycle or DC value (fan speed) in range:
+	    0 (stop) to 255 (full)
+pwm[1-2]_enable - this file controls mode of fan/temperature control:
+            * 0 Manual Mode
+            * 1 Thermal Cruise
+            * 2 Smart Fan II
+            * 4 FAN_SET
+pwm[1-2]_mode - Select PWM of DC mode
+            * 0 DC
+            * 1 PWM
+tolerance[1-2] - Value in degrees of Celsius (degC) for +- T
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index cf6b6cb..ef1efa7 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -95,4 +95,4 @@
 the SMBus on all IBM systems (detected using DMI data.)
 
 For additional information, read:
-http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad
+http://www.lm-sensors.org/browser/lm-sensors/trunk/README.thinkpad
diff --git a/Documentation/scsi/ChangeLog.arcmsr b/Documentation/scsi/ChangeLog.arcmsr
index cd8403a..de2bcac 100644
--- a/Documentation/scsi/ChangeLog.arcmsr
+++ b/Documentation/scsi/ChangeLog.arcmsr
@@ -68,4 +68,45 @@
 **						2. modify the arcmsr_pci_slot_reset function
 **						3. modify the arcmsr_pci_ers_disconnect_forepart function
 **						4. modify the arcmsr_pci_ers_need_reset_forepart function
+** 1.20.00.15   09/27/2007	 Erich Chen & Nick Cheng
+**						1. add arcmsr_enable_eoi_mode() on adapter Type B
+** 						2. add readl(reg->iop2drv_doorbell_reg) in arcmsr_handle_hbb_isr()
+**						in case of the doorbell interrupt clearance is cached
+** 1.20.00.15   10/01/2007	 Erich Chen & Nick Cheng
+**						1. modify acb->devstate[i][j]
+**						as ARECA_RAID_GOOD instead of
+**						ARECA_RAID_GONE in arcmsr_alloc_ccb_pool
+** 1.20.00.15   11/06/2007       Erich Chen & Nick Cheng
+**						1. add conditional declaration for
+** 						arcmsr_pci_error_detected() and
+**						arcmsr_pci_slot_reset
+** 1.20.00.15	11/23/2007       Erich Chen & Nick Cheng
+**						1.check if the sg list member number
+**						exceeds arcmsr default limit in arcmsr_build_ccb()
+**						2.change the returned value type of arcmsr_build_ccb()
+**						from "void" to "int"
+**						3.add the conditional check if arcmsr_build_ccb()
+**						returns FAILED
+** 1.20.00.15	12/04/2007	 Erich Chen & Nick Cheng
+**						1. modify arcmsr_drain_donequeue() to ignore unknown
+**						command and let kernel process command timeout.
+**						This could handle IO request violating max. segments
+**						while Linux XFS over DM-CRYPT.
+**						Thanks to Milan Broz's comments <mbroz@redhat.com>
+** 1.20.00.15	12/24/2007	 Erich Chen & Nick Cheng
+**						1.fix the portability problems
+**						2.fix type B where we should _not_ iounmap() acb->pmu;
+**						it's not ioremapped.
+**						3.add return -ENOMEM if ioremap() fails
+**						4.transfer IS_SG64_ADDR w/ cpu_to_le32()
+**						in arcmsr_build_ccb
+**						5. modify acb->devstate[i][j] as ARECA_RAID_GONE instead of
+**						ARECA_RAID_GOOD in arcmsr_alloc_ccb_pool()
+**						6.fix arcmsr_cdb->Context as (unsigned long)arcmsr_cdb
+**						7.add the checking state of
+**						(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT) == 0
+**						in arcmsr_handle_hba_isr
+**						8.replace pci_alloc_consistent()/pci_free_consistent() with kmalloc()/kfree() in arcmsr_iop_message_xfer()
+**						9. fix the release of dma memory for type B in arcmsr_free_ccb_pool()
+**						10.fix the arcmsr_polling_hbb_ccbdone()
 **************************************************************************
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 6f70f2b..a6d5354 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -1407,7 +1407,7 @@
 =======
 The following people have contributed to this document:
         Mike Anderson <andmike at us dot ibm dot com>
-        James Bottomley <James dot Bottomley at steeleye dot com> 
+        James Bottomley <James dot Bottomley at hansenpartnership dot com>
         Patrick Mansfield <patmans at us dot ibm dot com> 
         Christoph Hellwig <hch at infradead dot org>
         Doug Ledford <dledford at redhat dot com>
diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c
index 488c1f3..7123fee 100644
--- a/Documentation/vm/slabinfo.c
+++ b/Documentation/vm/slabinfo.c
@@ -32,6 +32,13 @@
 	int sanity_checks, slab_size, store_user, trace;
 	int order, poison, reclaim_account, red_zone;
 	unsigned long partial, objects, slabs;
+	unsigned long alloc_fastpath, alloc_slowpath;
+	unsigned long free_fastpath, free_slowpath;
+	unsigned long free_frozen, free_add_partial, free_remove_partial;
+	unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill;
+	unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
+	unsigned long deactivate_to_head, deactivate_to_tail;
+	unsigned long deactivate_remote_frees;
 	int numa[MAX_NODES];
 	int numa_partial[MAX_NODES];
 } slabinfo[MAX_SLABS];
@@ -64,8 +71,10 @@
 int show_single_ref = 0;
 int show_totals = 0;
 int sort_size = 0;
+int sort_active = 0;
 int set_debug = 0;
 int show_ops = 0;
+int show_activity = 0;
 
 /* Debug options */
 int sanity = 0;
@@ -93,8 +102,10 @@
 	printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n"
 		"slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
 		"-a|--aliases           Show aliases\n"
+		"-A|--activity          Most active slabs first\n"
 		"-d<options>|--debug=<options> Set/Clear Debug options\n"
-		"-e|--empty		Show empty slabs\n"
+		"-D|--display-active    Switch line format to activity\n"
+		"-e|--empty             Show empty slabs\n"
 		"-f|--first-alias       Show first alias\n"
 		"-h|--help              Show usage information\n"
 		"-i|--inverted          Inverted list\n"
@@ -281,8 +292,11 @@
 
 void first_line(void)
 {
-	printf("Name                   Objects Objsize    Space "
-		"Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
+	if (show_activity)
+		printf("Name                   Objects    Alloc     Free   %%Fast\n");
+	else
+		printf("Name                   Objects Objsize    Space "
+			"Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
 }
 
 /*
@@ -309,6 +323,12 @@
 	return 	s->slabs * (page_size << s->order);
 }
 
+unsigned long slab_activity(struct slabinfo *s)
+{
+	return 	s->alloc_fastpath + s->free_fastpath +
+		s->alloc_slowpath + s->free_slowpath;
+}
+
 void slab_numa(struct slabinfo *s, int mode)
 {
 	int node;
@@ -392,6 +412,71 @@
 	return "Off";
 }
 
+void slab_stats(struct slabinfo *s)
+{
+	unsigned long total_alloc;
+	unsigned long total_free;
+	unsigned long total;
+
+	if (!s->alloc_slab)
+		return;
+
+	total_alloc = s->alloc_fastpath + s->alloc_slowpath;
+	total_free = s->free_fastpath + s->free_slowpath;
+
+	if (!total_alloc)
+		return;
+
+	printf("\n");
+	printf("Slab Perf Counter       Alloc     Free %%Al %%Fr\n");
+	printf("--------------------------------------------------\n");
+	printf("Fastpath             %8lu %8lu %3lu %3lu\n",
+		s->alloc_fastpath, s->free_fastpath,
+		s->alloc_fastpath * 100 / total_alloc,
+		s->free_fastpath * 100 / total_free);
+	printf("Slowpath             %8lu %8lu %3lu %3lu\n",
+		total_alloc - s->alloc_fastpath, s->free_slowpath,
+		(total_alloc - s->alloc_fastpath) * 100 / total_alloc,
+		s->free_slowpath * 100 / total_free);
+	printf("Page Alloc           %8lu %8lu %3lu %3lu\n",
+		s->alloc_slab, s->free_slab,
+		s->alloc_slab * 100 / total_alloc,
+		s->free_slab * 100 / total_free);
+	printf("Add partial          %8lu %8lu %3lu %3lu\n",
+		s->deactivate_to_head + s->deactivate_to_tail,
+		s->free_add_partial,
+		(s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc,
+		s->free_add_partial * 100 / total_free);
+	printf("Remove partial       %8lu %8lu %3lu %3lu\n",
+		s->alloc_from_partial, s->free_remove_partial,
+		s->alloc_from_partial * 100 / total_alloc,
+		s->free_remove_partial * 100 / total_free);
+
+	printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
+		s->deactivate_remote_frees, s->free_frozen,
+		s->deactivate_remote_frees * 100 / total_alloc,
+		s->free_frozen * 100 / total_free);
+
+	printf("Total                %8lu %8lu\n\n", total_alloc, total_free);
+
+	if (s->cpuslab_flush)
+		printf("Flushes %8lu\n", s->cpuslab_flush);
+
+	if (s->alloc_refill)
+		printf("Refill %8lu\n", s->alloc_refill);
+
+	total = s->deactivate_full + s->deactivate_empty +
+			s->deactivate_to_head + s->deactivate_to_tail;
+
+	if (total)
+		printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) "
+			"ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n",
+			s->deactivate_full, (s->deactivate_full * 100) / total,
+			s->deactivate_empty, (s->deactivate_empty * 100) / total,
+			s->deactivate_to_head, (s->deactivate_to_head * 100) / total,
+			s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
+}
+
 void report(struct slabinfo *s)
 {
 	if (strcmp(s->name, "*") == 0)
@@ -430,6 +515,7 @@
 	ops(s);
 	show_tracking(s);
 	slab_numa(s, 1);
+	slab_stats(s);
 }
 
 void slabcache(struct slabinfo *s)
@@ -479,13 +565,27 @@
 		*p++ = 'T';
 
 	*p = 0;
-	printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
-		s->name, s->objects, s->object_size, size_str, dist_str,
-		s->objs_per_slab, s->order,
-		s->slabs ? (s->partial * 100) / s->slabs : 100,
-		s->slabs ? (s->objects * s->object_size * 100) /
-			(s->slabs * (page_size << s->order)) : 100,
-		flags);
+	if (show_activity) {
+		unsigned long total_alloc;
+		unsigned long total_free;
+
+		total_alloc = s->alloc_fastpath + s->alloc_slowpath;
+		total_free = s->free_fastpath + s->free_slowpath;
+
+		printf("%-21s %8ld %8ld %8ld %3ld %3ld \n",
+			s->name, s->objects,
+			total_alloc, total_free,
+			total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
+			total_free ? (s->free_fastpath * 100 / total_free) : 0);
+	}
+	else
+		printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
+			s->name, s->objects, s->object_size, size_str, dist_str,
+			s->objs_per_slab, s->order,
+			s->slabs ? (s->partial * 100) / s->slabs : 100,
+			s->slabs ? (s->objects * s->object_size * 100) /
+				(s->slabs * (page_size << s->order)) : 100,
+			flags);
 }
 
 /*
@@ -892,6 +992,8 @@
 
 			if (sort_size)
 				result = slab_size(s1) < slab_size(s2);
+			else if (sort_active)
+				result = slab_activity(s1) < slab_activity(s2);
 			else
 				result = strcasecmp(s1->name, s2->name);
 
@@ -1074,6 +1176,23 @@
 			free(t);
 			slab->store_user = get_obj("store_user");
 			slab->trace = get_obj("trace");
+			slab->alloc_fastpath = get_obj("alloc_fastpath");
+			slab->alloc_slowpath = get_obj("alloc_slowpath");
+			slab->free_fastpath = get_obj("free_fastpath");
+			slab->free_slowpath = get_obj("free_slowpath");
+			slab->free_frozen= get_obj("free_frozen");
+			slab->free_add_partial = get_obj("free_add_partial");
+			slab->free_remove_partial = get_obj("free_remove_partial");
+			slab->alloc_from_partial = get_obj("alloc_from_partial");
+			slab->alloc_slab = get_obj("alloc_slab");
+			slab->alloc_refill = get_obj("alloc_refill");
+			slab->free_slab = get_obj("free_slab");
+			slab->cpuslab_flush = get_obj("cpuslab_flush");
+			slab->deactivate_full = get_obj("deactivate_full");
+			slab->deactivate_empty = get_obj("deactivate_empty");
+			slab->deactivate_to_head = get_obj("deactivate_to_head");
+			slab->deactivate_to_tail = get_obj("deactivate_to_tail");
+			slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
 			chdir("..");
 			if (slab->name[0] == ':')
 				alias_targets++;
@@ -1124,7 +1243,9 @@
 
 struct option opts[] = {
 	{ "aliases", 0, NULL, 'a' },
+	{ "activity", 0, NULL, 'A' },
 	{ "debug", 2, NULL, 'd' },
+	{ "display-activity", 0, NULL, 'D' },
 	{ "empty", 0, NULL, 'e' },
 	{ "first-alias", 0, NULL, 'f' },
 	{ "help", 0, NULL, 'h' },
@@ -1149,7 +1270,7 @@
 
 	page_size = getpagesize();
 
-	while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS",
+	while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTS",
 						opts, NULL)) != -1)
 		switch (c) {
 		case '1':
@@ -1158,11 +1279,17 @@
 		case 'a':
 			show_alias = 1;
 			break;
+		case 'A':
+			sort_active = 1;
+			break;
 		case 'd':
 			set_debug = 1;
 			if (!debug_opt_scan(optarg))
 				fatal("Invalid debug option '%s'\n", optarg);
 			break;
+		case 'D':
+			show_activity = 1;
+			break;
 		case 'e':
 			show_empty = 1;
 			break;
diff --git a/MAINTAINERS b/MAINTAINERS
index aefd23f..2cdb591 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2150,6 +2150,14 @@
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+IPWIRELES DRIVER
+P:	Jiri Kosina
+M:	jkosina@suse.cz
+P:	David Sterba
+M:	dsterba@suse.cz
+S:	Maintained
+T:	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git
+
 IRDA SUBSYSTEM
 P:	Samuel Ortiz
 M:	samuel@sortiz.org
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 3ee9186..f85b928 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -335,7 +335,7 @@
 	if (dump->start_stack < TASK_SIZE)
 		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
 
-	dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
+	dump->u_ar0 = offsetof(struct user, regs);
 	sw = ((struct switch_stack *)regs) - 1;
 	dump->regs.d1 = regs->d1;
 	dump->regs.d2 = regs->d2;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index e6e4928..4b749c4 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -313,7 +313,7 @@
 	DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
 	DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
 	DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
-	DEFINE(CLOCK_REALTIME_RES, (KTIME_MONOTONIC_RES).tv64);
+	DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
 
 #ifdef CONFIG_BUG
 	DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c95482b..9d0aced 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -52,6 +52,10 @@
 config SEMAPHORE_SLEEPERS
 	def_bool y
 
+config FAST_CMPXCHG_LOCAL
+	bool
+	default y
+
 config MMU
 	def_bool y
 
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig
index f25facd..00b8a84 100644
--- a/drivers/char/pcmcia/Kconfig
+++ b/drivers/char/pcmcia/Kconfig
@@ -43,5 +43,14 @@
 	  (http://www.omnikey.com/), or a current development version of OpenCT
 	  (http://www.opensc.org/).
 
+config IPWIRELESS
+	tristate "IPWireless 3G UMTS PCMCIA card support"
+	depends on PCMCIA
+	select PPP
+	help
+	  This is a driver for 3G UMTS PCMCIA card from IPWireless company. In
+	  some countries (for example Czech Republic, T-Mobile ISP) this card
+	  is shipped for service called UMTS 4G.
+
 endmenu
 
diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile
index 0aae209..be8f287 100644
--- a/drivers/char/pcmcia/Makefile
+++ b/drivers/char/pcmcia/Makefile
@@ -4,6 +4,8 @@
 # Makefile for the Linux PCMCIA char device drivers.
 #
 
+obj-y += ipwireless/
+
 obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o
 obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o
 obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o
diff --git a/drivers/char/pcmcia/ipwireless/Makefile b/drivers/char/pcmcia/ipwireless/Makefile
new file mode 100644
index 0000000..b71eb59
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/Makefile
@@ -0,0 +1,10 @@
+#
+# drivers/char/pcmcia/ipwireless/Makefile
+#
+# Makefile for the IPWireless driver
+#
+
+obj-$(CONFIG_IPWIRELESS) += ipwireless.o
+
+ipwireless-objs := hardware.o main.o network.o tty.o
+
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c
new file mode 100644
index 0000000..1f978ff
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/hardware.c
@@ -0,0 +1,1787 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "hardware.h"
+#include "setup_protocol.h"
+#include "network.h"
+#include "main.h"
+
+static void ipw_send_setup_packet(struct ipw_hardware *hw);
+static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
+					 unsigned int address,
+					 unsigned char *data, int len,
+					 int is_last);
+static void ipwireless_setup_timer(unsigned long data);
+static void handle_received_CTRL_packet(struct ipw_hardware *hw,
+		unsigned int channel_idx, unsigned char *data, int len);
+
+/*#define TIMING_DIAGNOSTICS*/
+
+#ifdef TIMING_DIAGNOSTICS
+
+static struct timing_stats {
+	unsigned long last_report_time;
+	unsigned long read_time;
+	unsigned long write_time;
+	unsigned long read_bytes;
+	unsigned long write_bytes;
+	unsigned long start_time;
+};
+
+static void start_timing(void)
+{
+	timing_stats.start_time = jiffies;
+}
+
+static void end_read_timing(unsigned length)
+{
+	timing_stats.read_time += (jiffies - start_time);
+	timing_stats.read_bytes += length + 2;
+	report_timing();
+}
+
+static void end_write_timing(unsigned length)
+{
+	timing_stats.write_time += (jiffies - start_time);
+	timing_stats.write_bytes += length + 2;
+	report_timing();
+}
+
+static void report_timing(void)
+{
+	unsigned long since = jiffies - timing_stats.last_report_time;
+
+	/* If it's been more than one second... */
+	if (since >= HZ) {
+		int first = (timing_stats.last_report_time == 0);
+
+		timing_stats.last_report_time = jiffies;
+		if (!first)
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": %u us elapsed - read %lu bytes in %u us, "
+			       "wrote %lu bytes in %u us\n",
+			       jiffies_to_usecs(since),
+			       timing_stats.read_bytes,
+			       jiffies_to_usecs(timing_stats.read_time),
+			       timing_stats.write_bytes,
+			       jiffies_to_usecs(timing_stats.write_time));
+
+		timing_stats.read_time = 0;
+		timing_stats.write_time = 0;
+		timing_stats.read_bytes = 0;
+		timing_stats.write_bytes = 0;
+	}
+}
+#else
+static void start_timing(void) { }
+static void end_read_timing(unsigned length) { }
+static void end_write_timing(unsigned length) { }
+#endif
+
+/* Imported IPW definitions */
+
+#define LL_MTU_V1 318
+#define LL_MTU_V2 250
+#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2)
+
+#define PRIO_DATA  2
+#define PRIO_CTRL  1
+#define PRIO_SETUP 0
+
+/* Addresses */
+#define ADDR_SETUP_PROT 0
+
+/* Protocol ids */
+enum {
+	/* Identifier for the Com Data protocol */
+	TL_PROTOCOLID_COM_DATA = 0,
+
+	/* Identifier for the Com Control protocol */
+	TL_PROTOCOLID_COM_CTRL = 1,
+
+	/* Identifier for the Setup protocol */
+	TL_PROTOCOLID_SETUP = 2
+};
+
+/* Number of bytes in NL packet header (cannot do
+ * sizeof(nl_packet_header) since it's a bitfield) */
+#define NL_FIRST_PACKET_HEADER_SIZE        3
+
+/* Number of bytes in NL packet header (cannot do
+ * sizeof(nl_packet_header) since it's a bitfield) */
+#define NL_FOLLOWING_PACKET_HEADER_SIZE    1
+
+struct nl_first_packet_header {
+#if defined(__BIG_ENDIAN_BITFIELD)
+	unsigned char packet_rank:2;
+	unsigned char address:3;
+	unsigned char protocol:3;
+#else
+	unsigned char protocol:3;
+	unsigned char address:3;
+	unsigned char packet_rank:2;
+#endif
+	unsigned char length_lsb;
+	unsigned char length_msb;
+};
+
+struct nl_packet_header {
+#if defined(__BIG_ENDIAN_BITFIELD)
+	unsigned char packet_rank:2;
+	unsigned char address:3;
+	unsigned char protocol:3;
+#else
+	unsigned char protocol:3;
+	unsigned char address:3;
+	unsigned char packet_rank:2;
+#endif
+};
+
+/* Value of 'packet_rank' above */
+#define NL_INTERMEDIATE_PACKET    0x0
+#define NL_LAST_PACKET            0x1
+#define NL_FIRST_PACKET           0x2
+
+union nl_packet {
+	/* Network packet header of the first packet (a special case) */
+	struct nl_first_packet_header hdr_first;
+	/* Network packet header of the following packets (if any) */
+	struct nl_packet_header hdr;
+	/* Complete network packet (header + data) */
+	unsigned char rawpkt[LL_MTU_MAX];
+} __attribute__ ((__packed__));
+
+#define HW_VERSION_UNKNOWN -1
+#define HW_VERSION_1 1
+#define HW_VERSION_2 2
+
+/* IPW I/O ports */
+#define IOIER 0x00		/* Interrupt Enable Register */
+#define IOIR  0x02		/* Interrupt Source/ACK register */
+#define IODCR 0x04		/* Data Control Register */
+#define IODRR 0x06		/* Data Read Register */
+#define IODWR 0x08		/* Data Write Register */
+#define IOESR 0x0A		/* Embedded Driver Status Register */
+#define IORXR 0x0C		/* Rx Fifo Register (Host to Embedded) */
+#define IOTXR 0x0E		/* Tx Fifo Register (Embedded to Host) */
+
+/* I/O ports and bit definitions for version 1 of the hardware */
+
+/* IER bits*/
+#define IER_RXENABLED   0x1
+#define IER_TXENABLED   0x2
+
+/* ISR bits */
+#define IR_RXINTR       0x1
+#define IR_TXINTR       0x2
+
+/* DCR bits */
+#define DCR_RXDONE      0x1
+#define DCR_TXDONE      0x2
+#define DCR_RXRESET     0x4
+#define DCR_TXRESET     0x8
+
+/* I/O ports and bit definitions for version 2 of the hardware */
+
+struct MEMCCR {
+	unsigned short reg_config_option;	/* PCCOR: Configuration Option Register */
+	unsigned short reg_config_and_status;	/* PCCSR: Configuration and Status Register */
+	unsigned short reg_pin_replacement;	/* PCPRR: Pin Replacemant Register */
+	unsigned short reg_socket_and_copy;	/* PCSCR: Socket and Copy Register */
+	unsigned short reg_ext_status;		/* PCESR: Extendend Status Register */
+	unsigned short reg_io_base;		/* PCIOB: I/O Base Register */
+};
+
+struct MEMINFREG {
+	unsigned short memreg_tx_old;	/* TX Register (R/W) */
+	unsigned short pad1;
+	unsigned short memreg_rx_done;	/* RXDone Register (R/W) */
+	unsigned short pad2;
+	unsigned short memreg_rx;	/* RX Register (R/W) */
+	unsigned short pad3;
+	unsigned short memreg_pc_interrupt_ack;	/* PC intr Ack Register (W) */
+	unsigned short pad4;
+	unsigned long memreg_card_present;/* Mask for Host to check (R) for
+					   * CARD_PRESENT_VALUE */
+	unsigned short memreg_tx_new;	/* TX2 (new) Register (R/W) */
+};
+
+#define IODMADPR 0x00		/* DMA Data Port Register (R/W) */
+
+#define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
+
+#define MEMTX_TX                       0x0001
+#define MEMRX_RX                       0x0001
+#define MEMRX_RX_DONE                  0x0001
+#define MEMRX_PCINTACKK                0x0001
+#define MEMRX_MEMSPURIOUSINT           0x0001
+
+#define NL_NUM_OF_PRIORITIES       3
+#define NL_NUM_OF_PROTOCOLS        3
+#define NL_NUM_OF_ADDRESSES        NO_OF_IPW_CHANNELS
+
+struct ipw_hardware {
+	unsigned int base_port;
+	short hw_version;
+	unsigned short ll_mtu;
+	spinlock_t spinlock;
+
+	int initializing;
+	int init_loops;
+	struct timer_list setup_timer;
+
+	int tx_ready;
+	struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
+	/* True if any packets are queued for transmission */
+	int tx_queued;
+
+	int rx_bytes_queued;
+	struct list_head rx_queue;
+	/* Pool of rx_packet structures that are not currently used. */
+	struct list_head rx_pool;
+	int rx_pool_size;
+	/* True if reception of data is blocked while userspace processes it. */
+	int blocking_rx;
+	/* True if there is RX data ready on the hardware. */
+	int rx_ready;
+	unsigned short last_memtx_serial;
+	/*
+	 * Newer versions of the V2 card firmware send serial numbers in the
+	 * MemTX register. 'serial_number_detected' is set true when we detect
+	 * a non-zero serial number (indicating the new firmware).  Thereafter,
+	 * the driver can safely ignore the Timer Recovery re-sends to avoid
+	 * out-of-sync problems.
+	 */
+	int serial_number_detected;
+	struct work_struct work_rx;
+
+	/* True if we are to send the set-up data to the hardware. */
+	int to_setup;
+
+	/* Card has been removed */
+	int removed;
+	/* Saved irq value when we disable the interrupt. */
+	int irq;
+	/* True if this driver is shutting down. */
+	int shutting_down;
+	/* Modem control lines */
+	unsigned int control_lines[NL_NUM_OF_ADDRESSES];
+	struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES];
+
+	struct tasklet_struct tasklet;
+
+	/* The handle for the network layer, for the sending of events to it. */
+	struct ipw_network *network;
+	struct MEMINFREG __iomem *memory_info_regs;
+	struct MEMCCR __iomem *memregs_CCR;
+	void (*reboot_callback) (void *data);
+	void *reboot_callback_data;
+
+	unsigned short __iomem *memreg_tx;
+};
+
+/*
+ * Packet info structure for tx packets.
+ * Note: not all the fields defined here are required for all protocols
+ */
+struct ipw_tx_packet {
+	struct list_head queue;
+	/* channel idx + 1 */
+	unsigned char dest_addr;
+	/* SETUP, CTRL or DATA */
+	unsigned char protocol;
+	/* Length of data block, which starts at the end of this structure */
+	unsigned short length;
+	/* Sending state */
+	/* Offset of where we've sent up to so far */
+	unsigned long offset;
+	/* Count of packet fragments, starting at 0 */
+	int fragment_count;
+
+	/* Called after packet is sent and before is freed */
+	void (*packet_callback) (void *cb_data, unsigned int packet_length);
+	void *callback_data;
+};
+
+/* Signals from DTE */
+#define COMCTRL_RTS	0
+#define COMCTRL_DTR	1
+
+/* Signals from DCE */
+#define COMCTRL_CTS	2
+#define COMCTRL_DCD	3
+#define COMCTRL_DSR	4
+#define COMCTRL_RI	5
+
+struct ipw_control_packet_body {
+	/* DTE signal or DCE signal */
+	unsigned char sig_no;
+	/* 0: set signal, 1: clear signal */
+	unsigned char value;
+} __attribute__ ((__packed__));
+
+struct ipw_control_packet {
+	struct ipw_tx_packet header;
+	struct ipw_control_packet_body body;
+};
+
+struct ipw_rx_packet {
+	struct list_head queue;
+	unsigned int capacity;
+	unsigned int length;
+	unsigned int protocol;
+	unsigned int channel_idx;
+};
+
+#ifdef IPWIRELESS_STATE_DEBUG
+int ipwireless_dump_hardware_state(char *p, size_t limit,
+				   struct ipw_hardware *hw)
+{
+	return snprintf(p, limit,
+			"debug: initializing=%d\n"
+			"debug: tx_ready=%d\n"
+			"debug: tx_queued=%d\n"
+			"debug: rx_ready=%d\n"
+			"debug: rx_bytes_queued=%d\n"
+			"debug: blocking_rx=%d\n"
+			"debug: removed=%d\n"
+			"debug: hardware.shutting_down=%d\n"
+			"debug: to_setup=%d\n",
+			hw->initializing,
+			hw->tx_ready,
+			hw->tx_queued,
+			hw->rx_ready,
+			hw->rx_bytes_queued,
+			hw->blocking_rx,
+			hw->removed,
+			hw->shutting_down,
+			hw->to_setup);
+}
+#endif
+
+static char *data_type(const unsigned char *buf, unsigned length)
+{
+	struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
+
+	if (length == 0)
+		return "     ";
+
+	if (hdr->packet_rank & NL_FIRST_PACKET) {
+		switch (hdr->protocol) {
+		case TL_PROTOCOLID_COM_DATA:	return "DATA ";
+		case TL_PROTOCOLID_COM_CTRL:	return "CTRL ";
+		case TL_PROTOCOLID_SETUP:	return "SETUP";
+		default: return "???? ";
+		}
+	} else
+		return "     ";
+}
+
+#define DUMP_MAX_BYTES 64
+
+static void dump_data_bytes(const char *type, const unsigned char *data,
+			    unsigned length)
+{
+	char prefix[56];
+
+	sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ",
+			type, data_type(data, length));
+	print_hex_dump_bytes(prefix, 0, (void *)data,
+			length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
+}
+
+static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
+			    unsigned length)
+{
+	int i;
+	unsigned long flags;
+
+	start_timing();
+
+	if (length == 0)
+		return 0;
+
+	if (length > hw->ll_mtu)
+		return -1;
+
+	if (ipwireless_debug)
+		dump_data_bytes("send", data, length);
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+
+	if (hw->hw_version == HW_VERSION_1) {
+		outw((unsigned short) length, hw->base_port + IODWR);
+
+		for (i = 0; i < length; i += 2) {
+			unsigned short d = data[i];
+			__le16 raw_data;
+
+			if (likely(i + 1 < length))
+				d |= data[i + 1] << 8;
+			raw_data = cpu_to_le16(d);
+			outw(raw_data, hw->base_port + IODWR);
+		}
+
+		outw(DCR_TXDONE, hw->base_port + IODCR);
+	} else if (hw->hw_version == HW_VERSION_2) {
+		outw((unsigned short) length, hw->base_port + IODMADPR);
+
+		for (i = 0; i < length; i += 2) {
+			unsigned short d = data[i];
+			__le16 raw_data;
+
+			if ((i + 1 < length))
+				d |= data[i + 1] << 8;
+			raw_data = cpu_to_le16(d);
+			outw(raw_data, hw->base_port + IODMADPR);
+		}
+		while ((i & 3) != 2) {
+			outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR);
+			i += 2;
+		}
+		writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
+	}
+
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+
+	end_write_timing(length);
+
+	return 0;
+}
+
+static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
+{
+	unsigned short fragment_data_len;
+	unsigned short data_left = packet->length - packet->offset;
+	unsigned short header_size;
+	union nl_packet pkt;
+
+	header_size =
+	    (packet->fragment_count == 0)
+	    ? NL_FIRST_PACKET_HEADER_SIZE
+	    : NL_FOLLOWING_PACKET_HEADER_SIZE;
+	fragment_data_len = hw->ll_mtu - header_size;
+	if (data_left < fragment_data_len)
+		fragment_data_len = data_left;
+
+	pkt.hdr_first.protocol = packet->protocol;
+	pkt.hdr_first.address = packet->dest_addr;
+	pkt.hdr_first.packet_rank = 0;
+
+	/* First packet? */
+	if (packet->fragment_count == 0) {
+		pkt.hdr_first.packet_rank |= NL_FIRST_PACKET;
+		pkt.hdr_first.length_lsb = (unsigned char) packet->length;
+		pkt.hdr_first.length_msb =
+			(unsigned char) (packet->length >> 8);
+	}
+
+	memcpy(pkt.rawpkt + header_size,
+	       ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) +
+	       packet->offset, fragment_data_len);
+	packet->offset += fragment_data_len;
+	packet->fragment_count++;
+
+	/* Last packet? (May also be first packet.) */
+	if (packet->offset == packet->length)
+		pkt.hdr_first.packet_rank |= NL_LAST_PACKET;
+	do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len);
+
+	/* If this packet has unsent data, then re-queue it. */
+	if (packet->offset < packet->length) {
+		/*
+		 * Re-queue it at the head of the highest priority queue so
+		 * it goes before all other packets
+		 */
+		unsigned long flags;
+
+		spin_lock_irqsave(&hw->spinlock, flags);
+		list_add(&packet->queue, &hw->tx_queue[0]);
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+	} else {
+		if (packet->packet_callback)
+			packet->packet_callback(packet->callback_data,
+					packet->length);
+		kfree(packet);
+	}
+
+	return 0;
+}
+
+static void ipw_setup_hardware(struct ipw_hardware *hw)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	if (hw->hw_version == HW_VERSION_1) {
+		/* Reset RX FIFO */
+		outw(DCR_RXRESET, hw->base_port + IODCR);
+		/* SB: Reset TX FIFO */
+		outw(DCR_TXRESET, hw->base_port + IODCR);
+
+		/* Enable TX and RX interrupts. */
+		outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER);
+	} else {
+		/*
+		 * Set INTRACK bit (bit 0), which means we must explicitly
+		 * acknowledge interrupts by clearing bit 2 of reg_config_and_status.
+		 */
+		unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
+
+		csr |= 1;
+		writew(csr, &hw->memregs_CCR->reg_config_and_status);
+	}
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+}
+
+/*
+ * If 'packet' is NULL, then this function allocates a new packet, setting its
+ * length to 0 and ensuring it has the specified minimum amount of free space.
+ *
+ * If 'packet' is not NULL, then this function enlarges it if it doesn't
+ * have the specified minimum amount of free space.
+ *
+ */
+static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
+					   struct ipw_rx_packet *packet,
+					   int minimum_free_space)
+{
+
+	if (!packet) {
+		unsigned long flags;
+
+		/*
+		 * If this is the first fragment, then we will need to fetch a
+		 * packet to put it in.
+		 */
+		spin_lock_irqsave(&hw->spinlock, flags);
+		/* If we have one in our pool, then pull it out. */
+		if (!list_empty(&hw->rx_pool)) {
+			packet = list_first_entry(&hw->rx_pool,
+					struct ipw_rx_packet, queue);
+			list_del(&packet->queue);
+			hw->rx_pool_size--;
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+		} else {
+			/* Otherwise allocate a new one. */
+			static int min_capacity = 256;
+			int new_capacity;
+
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+			new_capacity =
+			    minimum_free_space > min_capacity
+			    ? minimum_free_space
+			    : min_capacity;
+			packet = kmalloc(sizeof(struct ipw_rx_packet)
+					+ new_capacity, GFP_ATOMIC);
+			if (!packet)
+				return NULL;
+			packet->capacity = new_capacity;
+		}
+		packet->length = 0;
+	}
+
+	/*
+	 * If this packet does not have sufficient capacity for the data we
+	 * want to add, then make it bigger.
+	 */
+	if (packet->length + minimum_free_space > packet->capacity) {
+		struct ipw_rx_packet *old_packet = packet;
+
+		packet = kmalloc(sizeof(struct ipw_rx_packet) +
+				old_packet->length + minimum_free_space,
+				GFP_ATOMIC);
+		if (!packet)
+			return NULL;
+		memcpy(packet, old_packet,
+				sizeof(struct ipw_rx_packet)
+					+ old_packet->length);
+		packet->capacity = old_packet->length + minimum_free_space;
+		kfree(old_packet);
+	}
+
+	return packet;
+}
+
+static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet)
+{
+	if (hw->rx_pool_size > 6)
+		kfree(packet);
+	else {
+		hw->rx_pool_size++;
+		list_add_tail(&packet->queue, &hw->rx_pool);
+	}
+}
+
+static void queue_received_packet(struct ipw_hardware *hw,
+				  unsigned int protocol, unsigned int address,
+				  unsigned char *data, int length, int is_last)
+{
+	unsigned int channel_idx = address - 1;
+	struct ipw_rx_packet *packet = NULL;
+	unsigned long flags;
+
+	/* Discard packet if channel index is out of range. */
+	if (channel_idx >= NL_NUM_OF_ADDRESSES) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": data packet has bad address %u\n", address);
+		return;
+	}
+
+	/*
+	 * ->packet_assembler is safe to touch unlocked, this is the only place
+	 */
+	if (protocol == TL_PROTOCOLID_COM_DATA) {
+		struct ipw_rx_packet **assem =
+			&hw->packet_assembler[channel_idx];
+
+		/*
+		 * Create a new packet, or assembler already contains one
+		 * enlarge it by 'length' bytes.
+		 */
+		(*assem) = pool_allocate(hw, *assem, length);
+		if (!(*assem)) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+				": no memory for incomming data packet, dropped!\n");
+			return;
+		}
+		(*assem)->protocol = protocol;
+		(*assem)->channel_idx = channel_idx;
+
+		/* Append this packet data onto existing data. */
+		memcpy((unsigned char *)(*assem) +
+			       sizeof(struct ipw_rx_packet)
+				+ (*assem)->length, data, length);
+		(*assem)->length += length;
+		if (is_last) {
+			packet = *assem;
+			*assem = NULL;
+			/* Count queued DATA bytes only */
+			spin_lock_irqsave(&hw->spinlock, flags);
+			hw->rx_bytes_queued += packet->length;
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+		}
+	} else {
+		/* If it's a CTRL packet, don't assemble, just queue it. */
+		packet = pool_allocate(hw, NULL, length);
+		if (!packet) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+				": no memory for incomming ctrl packet, dropped!\n");
+			return;
+		}
+		packet->protocol = protocol;
+		packet->channel_idx = channel_idx;
+		memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet),
+				data, length);
+		packet->length = length;
+	}
+
+	/*
+	 * If this is the last packet, then send the assembled packet on to the
+	 * network layer.
+	 */
+	if (packet) {
+		spin_lock_irqsave(&hw->spinlock, flags);
+		list_add_tail(&packet->queue, &hw->rx_queue);
+		/* Block reception of incoming packets if queue is full. */
+		hw->blocking_rx =
+			hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
+
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+		schedule_work(&hw->work_rx);
+	}
+}
+
+/*
+ * Workqueue callback
+ */
+static void ipw_receive_data_work(struct work_struct *work_rx)
+{
+	struct ipw_hardware *hw =
+	    container_of(work_rx, struct ipw_hardware, work_rx);
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	while (!list_empty(&hw->rx_queue)) {
+		struct ipw_rx_packet *packet =
+			list_first_entry(&hw->rx_queue,
+					struct ipw_rx_packet, queue);
+
+		if (hw->shutting_down)
+			break;
+		list_del(&packet->queue);
+
+		/*
+		 * Note: ipwireless_network_packet_received must be called in a
+		 * process context (i.e. via schedule_work) because the tty
+		 * output code can sleep in the tty_flip_buffer_push call.
+		 */
+		if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
+			if (hw->network != NULL) {
+				/* If the network hasn't been disconnected. */
+				spin_unlock_irqrestore(&hw->spinlock, flags);
+				/*
+				 * This must run unlocked due to tty processing
+				 * and mutex locking
+				 */
+				ipwireless_network_packet_received(
+						hw->network,
+						packet->channel_idx,
+						(unsigned char *)packet
+						+ sizeof(struct ipw_rx_packet),
+						packet->length);
+				spin_lock_irqsave(&hw->spinlock, flags);
+			}
+			/* Count queued DATA bytes only */
+			hw->rx_bytes_queued -= packet->length;
+		} else {
+			/*
+			 * This is safe to be called locked, callchain does
+			 * not block
+			 */
+			handle_received_CTRL_packet(hw, packet->channel_idx,
+					(unsigned char *)packet
+					+ sizeof(struct ipw_rx_packet),
+					packet->length);
+		}
+		pool_free(hw, packet);
+		/*
+		 * Unblock reception of incoming packets if queue is no longer
+		 * full.
+		 */
+		hw->blocking_rx =
+			hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
+		if (hw->shutting_down)
+			break;
+	}
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+}
+
+static void handle_received_CTRL_packet(struct ipw_hardware *hw,
+					unsigned int channel_idx,
+					unsigned char *data, int len)
+{
+	struct ipw_control_packet_body *body =
+		(struct ipw_control_packet_body *) data;
+	unsigned int changed_mask;
+
+	if (len != sizeof(struct ipw_control_packet_body)) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": control packet was %d bytes - wrong size!\n",
+		       len);
+		return;
+	}
+
+	switch (body->sig_no) {
+	case COMCTRL_CTS:
+		changed_mask = IPW_CONTROL_LINE_CTS;
+		break;
+	case COMCTRL_DCD:
+		changed_mask = IPW_CONTROL_LINE_DCD;
+		break;
+	case COMCTRL_DSR:
+		changed_mask = IPW_CONTROL_LINE_DSR;
+		break;
+	case COMCTRL_RI:
+		changed_mask = IPW_CONTROL_LINE_RI;
+		break;
+	default:
+		changed_mask = 0;
+	}
+
+	if (changed_mask != 0) {
+		if (body->value)
+			hw->control_lines[channel_idx] |= changed_mask;
+		else
+			hw->control_lines[channel_idx] &= ~changed_mask;
+		if (hw->network)
+			ipwireless_network_notify_control_line_change(
+					hw->network,
+					channel_idx,
+					hw->control_lines[channel_idx],
+					changed_mask);
+	}
+}
+
+static void handle_received_packet(struct ipw_hardware *hw,
+				   union nl_packet *packet,
+				   unsigned short len)
+{
+	unsigned int protocol = packet->hdr.protocol;
+	unsigned int address = packet->hdr.address;
+	unsigned int header_length;
+	unsigned char *data;
+	unsigned int data_len;
+	int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
+
+	if (packet->hdr.packet_rank & NL_FIRST_PACKET)
+		header_length = NL_FIRST_PACKET_HEADER_SIZE;
+	else
+		header_length = NL_FOLLOWING_PACKET_HEADER_SIZE;
+
+	data = packet->rawpkt + header_length;
+	data_len = len - header_length;
+	switch (protocol) {
+	case TL_PROTOCOLID_COM_DATA:
+	case TL_PROTOCOLID_COM_CTRL:
+		queue_received_packet(hw, protocol, address, data, data_len,
+				is_last);
+		break;
+	case TL_PROTOCOLID_SETUP:
+		handle_received_SETUP_packet(hw, address, data, data_len,
+				is_last);
+		break;
+	}
+}
+
+static void acknowledge_data_read(struct ipw_hardware *hw)
+{
+	if (hw->hw_version == HW_VERSION_1)
+		outw(DCR_RXDONE, hw->base_port + IODCR);
+	else
+		writew(MEMRX_PCINTACKK,
+				&hw->memory_info_regs->memreg_pc_interrupt_ack);
+}
+
+/*
+ * Retrieve a packet from the IPW hardware.
+ */
+static void do_receive_packet(struct ipw_hardware *hw)
+{
+	unsigned len;
+	unsigned int i;
+	unsigned char pkt[LL_MTU_MAX];
+
+	start_timing();
+
+	if (hw->hw_version == HW_VERSION_1) {
+		len = inw(hw->base_port + IODRR);
+		if (len > hw->ll_mtu) {
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": received a packet of %u bytes - "
+			       "longer than the MTU!\n", len);
+			outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
+			return;
+		}
+
+		for (i = 0; i < len; i += 2) {
+			__le16 raw_data = inw(hw->base_port + IODRR);
+			unsigned short data = le16_to_cpu(raw_data);
+
+			pkt[i] = (unsigned char) data;
+			pkt[i + 1] = (unsigned char) (data >> 8);
+		}
+	} else {
+		len = inw(hw->base_port + IODMADPR);
+		if (len > hw->ll_mtu) {
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": received a packet of %u bytes - "
+			       "longer than the MTU!\n", len);
+			writew(MEMRX_PCINTACKK,
+				&hw->memory_info_regs->memreg_pc_interrupt_ack);
+			return;
+		}
+
+		for (i = 0; i < len; i += 2) {
+			__le16 raw_data = inw(hw->base_port + IODMADPR);
+			unsigned short data = le16_to_cpu(raw_data);
+
+			pkt[i] = (unsigned char) data;
+			pkt[i + 1] = (unsigned char) (data >> 8);
+		}
+
+		while ((i & 3) != 2) {
+			inw(hw->base_port + IODMADPR);
+			i += 2;
+		}
+	}
+
+	acknowledge_data_read(hw);
+
+	if (ipwireless_debug)
+		dump_data_bytes("recv", pkt, len);
+
+	handle_received_packet(hw, (union nl_packet *) pkt, len);
+
+	end_read_timing(len);
+}
+
+static int get_current_packet_priority(struct ipw_hardware *hw)
+{
+	/*
+	 * If we're initializing, don't send anything of higher priority than
+	 * PRIO_SETUP.  The network layer therefore need not care about
+	 * hardware initialization - any of its stuff will simply be queued
+	 * until setup is complete.
+	 */
+	return (hw->to_setup || hw->initializing
+			? PRIO_SETUP + 1 :
+			NL_NUM_OF_PRIORITIES);
+}
+
+/*
+ * return 1 if something has been received from hw
+ */
+static int get_packets_from_hw(struct ipw_hardware *hw)
+{
+	int received = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	while (hw->rx_ready && !hw->blocking_rx) {
+		received = 1;
+		hw->rx_ready--;
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+
+		do_receive_packet(hw);
+
+		spin_lock_irqsave(&hw->spinlock, flags);
+	}
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+
+	return received;
+}
+
+/*
+ * Send pending packet up to given priority, prioritize SETUP data until
+ * hardware is fully setup.
+ *
+ * return 1 if more packets can be sent
+ */
+static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
+{
+	int more_to_send = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	if (hw->tx_queued && hw->tx_ready != 0) {
+		int priority;
+		struct ipw_tx_packet *packet = NULL;
+
+		hw->tx_ready--;
+
+		/* Pick a packet */
+		for (priority = 0; priority < priority_limit; priority++) {
+			if (!list_empty(&hw->tx_queue[priority])) {
+				packet = list_first_entry(
+						&hw->tx_queue[priority],
+						struct ipw_tx_packet,
+						queue);
+
+				list_del(&packet->queue);
+
+				break;
+			}
+		}
+		if (!packet) {
+			hw->tx_queued = 0;
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+			return 0;
+		}
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+
+		/* Send */
+		do_send_packet(hw, packet);
+
+		/* Check if more to send */
+		spin_lock_irqsave(&hw->spinlock, flags);
+		for (priority = 0; priority < priority_limit; priority++)
+			if (!list_empty(&hw->tx_queue[priority])) {
+				more_to_send = 1;
+				break;
+			}
+
+		if (!more_to_send)
+			hw->tx_queued = 0;
+	}
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+
+	return more_to_send;
+}
+
+/*
+ * Send and receive all queued packets.
+ */
+static void ipwireless_do_tasklet(unsigned long hw_)
+{
+	struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	if (hw->shutting_down) {
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+		return;
+	}
+
+	if (hw->to_setup == 1) {
+		/*
+		 * Initial setup data sent to hardware
+		 */
+		hw->to_setup = 2;
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+
+		ipw_setup_hardware(hw);
+		ipw_send_setup_packet(hw);
+
+		send_pending_packet(hw, PRIO_SETUP + 1);
+		get_packets_from_hw(hw);
+	} else {
+		int priority_limit = get_current_packet_priority(hw);
+		int again;
+
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+
+		do {
+			again = send_pending_packet(hw, priority_limit);
+			again |= get_packets_from_hw(hw);
+		} while (again);
+	}
+}
+
+/*
+ * return true if the card is physically present.
+ */
+static int is_card_present(struct ipw_hardware *hw)
+{
+	if (hw->hw_version == HW_VERSION_1)
+		return inw(hw->base_port + IOIR) != 0xFFFF;
+	else
+		return readl(&hw->memory_info_regs->memreg_card_present) ==
+		    CARD_PRESENT_VALUE;
+}
+
+static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
+						  struct ipw_hardware *hw)
+{
+	unsigned short irqn;
+
+	irqn = inw(hw->base_port + IOIR);
+
+	/* Check if card is present */
+	if (irqn == 0xFFFF)
+		return IRQ_NONE;
+	else if (irqn != 0) {
+		unsigned short ack = 0;
+		unsigned long flags;
+
+		/* Transmit complete. */
+		if (irqn & IR_TXINTR) {
+			ack |= IR_TXINTR;
+			spin_lock_irqsave(&hw->spinlock, flags);
+			hw->tx_ready++;
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+		}
+		/* Received data */
+		if (irqn & IR_RXINTR) {
+			ack |= IR_RXINTR;
+			spin_lock_irqsave(&hw->spinlock, flags);
+			hw->rx_ready++;
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+		}
+		if (ack != 0) {
+			outw(ack, hw->base_port + IOIR);
+			tasklet_schedule(&hw->tasklet);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw)
+{
+	unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
+
+	csr &= 0xfffd;
+	writew(csr, &hw->memregs_CCR->reg_config_and_status);
+}
+
+static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
+						     struct ipw_hardware *hw)
+{
+	int tx = 0;
+	int rx = 0;
+	int rx_repeat = 0;
+	int try_mem_tx_old;
+	unsigned long flags;
+
+	do {
+
+	unsigned short memtx = readw(hw->memreg_tx);
+	unsigned short memtx_serial;
+	unsigned short memrxdone =
+		readw(&hw->memory_info_regs->memreg_rx_done);
+
+	try_mem_tx_old = 0;
+
+	/* check whether the interrupt was generated by ipwireless card */
+	if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) {
+
+		/* check if the card uses memreg_tx_old register */
+		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
+			memtx = readw(&hw->memory_info_regs->memreg_tx_old);
+			if (memtx & MEMTX_TX) {
+				printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+					": Using memreg_tx_old\n");
+				hw->memreg_tx =
+					&hw->memory_info_regs->memreg_tx_old;
+			} else {
+				return IRQ_NONE;
+			}
+		} else {
+			return IRQ_NONE;
+		}
+	}
+
+	/*
+	 * See if the card is physically present. Note that while it is
+	 * powering up, it appears not to be present.
+	 */
+	if (!is_card_present(hw)) {
+		acknowledge_pcmcia_interrupt(hw);
+		return IRQ_HANDLED;
+	}
+
+	memtx_serial = memtx & (unsigned short) 0xff00;
+	if (memtx & MEMTX_TX) {
+		writew(memtx_serial, hw->memreg_tx);
+
+		if (hw->serial_number_detected) {
+			if (memtx_serial != hw->last_memtx_serial) {
+				hw->last_memtx_serial = memtx_serial;
+				spin_lock_irqsave(&hw->spinlock, flags);
+				hw->rx_ready++;
+				spin_unlock_irqrestore(&hw->spinlock, flags);
+				rx = 1;
+			} else
+				/* Ignore 'Timer Recovery' duplicates. */
+				rx_repeat = 1;
+		} else {
+			/*
+			 * If a non-zero serial number is seen, then enable
+			 * serial number checking.
+			 */
+			if (memtx_serial != 0) {
+				hw->serial_number_detected = 1;
+				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+					": memreg_tx serial num detected\n");
+
+				spin_lock_irqsave(&hw->spinlock, flags);
+				hw->rx_ready++;
+				spin_unlock_irqrestore(&hw->spinlock, flags);
+			}
+			rx = 1;
+		}
+	}
+	if (memrxdone & MEMRX_RX_DONE) {
+		writew(0, &hw->memory_info_regs->memreg_rx_done);
+		spin_lock_irqsave(&hw->spinlock, flags);
+		hw->tx_ready++;
+		spin_unlock_irqrestore(&hw->spinlock, flags);
+		tx = 1;
+	}
+	if (tx)
+		writew(MEMRX_PCINTACKK,
+				&hw->memory_info_regs->memreg_pc_interrupt_ack);
+
+	acknowledge_pcmcia_interrupt(hw);
+
+	if (tx || rx)
+		tasklet_schedule(&hw->tasklet);
+	else if (!rx_repeat) {
+		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
+			if (hw->serial_number_detected)
+				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
+					": spurious interrupt - new_tx mode\n");
+			else {
+				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
+					": no valid memreg_tx value - "
+					"switching to the old memreg_tx\n");
+				hw->memreg_tx =
+					&hw->memory_info_regs->memreg_tx_old;
+				try_mem_tx_old = 1;
+			}
+		} else
+			printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
+					": spurious interrupt - old_tx mode\n");
+	}
+
+	} while (try_mem_tx_old == 1);
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct ipw_hardware *hw = dev_id;
+
+	if (hw->hw_version == HW_VERSION_1)
+		return ipwireless_handle_v1_interrupt(irq, hw);
+	else
+		return ipwireless_handle_v2_v3_interrupt(irq, hw);
+}
+
+static void flush_packets_to_hw(struct ipw_hardware *hw)
+{
+	int priority_limit;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	priority_limit = get_current_packet_priority(hw);
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+
+	while (send_pending_packet(hw, priority_limit));
+}
+
+static void send_packet(struct ipw_hardware *hw, int priority,
+			struct ipw_tx_packet *packet)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->spinlock, flags);
+	list_add_tail(&packet->queue, &hw->tx_queue[priority]);
+	hw->tx_queued = 1;
+	spin_unlock_irqrestore(&hw->spinlock, flags);
+
+	flush_packets_to_hw(hw);
+}
+
+/* Create data packet, non-atomic allocation */
+static void *alloc_data_packet(int data_size,
+				unsigned char dest_addr,
+				unsigned char protocol)
+{
+	struct ipw_tx_packet *packet = kzalloc(
+			sizeof(struct ipw_tx_packet) + data_size,
+			GFP_ATOMIC);
+
+	if (!packet)
+		return NULL;
+
+	INIT_LIST_HEAD(&packet->queue);
+	packet->dest_addr = dest_addr;
+	packet->protocol = protocol;
+	packet->length = data_size;
+
+	return packet;
+}
+
+static void *alloc_ctrl_packet(int header_size,
+			       unsigned char dest_addr,
+			       unsigned char protocol,
+			       unsigned char sig_no)
+{
+	/*
+	 * sig_no is located right after ipw_tx_packet struct in every
+	 * CTRL or SETUP packets, we can use ipw_control_packet as a
+	 * common struct
+	 */
+	struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC);
+
+	if (!packet)
+		return NULL;
+
+	INIT_LIST_HEAD(&packet->header.queue);
+	packet->header.dest_addr = dest_addr;
+	packet->header.protocol = protocol;
+	packet->header.length = header_size - sizeof(struct ipw_tx_packet);
+	packet->body.sig_no = sig_no;
+
+	return packet;
+}
+
+int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
+			    unsigned char *data, unsigned int length,
+			    void (*callback) (void *cb, unsigned int length),
+			    void *callback_data)
+{
+	struct ipw_tx_packet *packet;
+
+	packet = alloc_data_packet(length,
+			       (unsigned char) (channel_idx + 1),
+			       TL_PROTOCOLID_COM_DATA);
+	if (!packet)
+		return -ENOMEM;
+	packet->packet_callback = callback;
+	packet->callback_data = callback_data;
+	memcpy((unsigned char *) packet +
+			sizeof(struct ipw_tx_packet), data, length);
+
+	send_packet(hw, PRIO_DATA, packet);
+	return 0;
+}
+
+static int set_control_line(struct ipw_hardware *hw, int prio,
+			   unsigned int channel_idx, int line, int state)
+{
+	struct ipw_control_packet *packet;
+	int protocolid = TL_PROTOCOLID_COM_CTRL;
+
+	if (prio == PRIO_SETUP)
+		protocolid = TL_PROTOCOLID_SETUP;
+
+	packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
+			(unsigned char) (channel_idx + 1),
+			protocolid, line);
+	if (!packet)
+		return -ENOMEM;
+	packet->header.length = sizeof(struct ipw_control_packet_body);
+	packet->body.value = (unsigned char) (state == 0 ? 0 : 1);
+	send_packet(hw, prio, &packet->header);
+	return 0;
+}
+
+
+static int set_DTR(struct ipw_hardware *hw, int priority,
+		   unsigned int channel_idx, int state)
+{
+	if (state != 0)
+		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR;
+	else
+		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR;
+
+	return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state);
+}
+
+static int set_RTS(struct ipw_hardware *hw, int priority,
+		   unsigned int channel_idx, int state)
+{
+	if (state != 0)
+		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS;
+	else
+		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS;
+
+	return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state);
+}
+
+int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
+		       int state)
+{
+	return set_DTR(hw, PRIO_CTRL, channel_idx, state);
+}
+
+int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
+		       int state)
+{
+	return set_RTS(hw, PRIO_CTRL, channel_idx, state);
+}
+
+struct ipw_setup_get_version_query_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_get_version_qry body;
+};
+
+struct ipw_setup_config_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_config_msg body;
+};
+
+struct ipw_setup_config_done_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_config_done_msg body;
+};
+
+struct ipw_setup_open_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_open_msg body;
+};
+
+struct ipw_setup_info_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_info_msg body;
+};
+
+struct ipw_setup_reboot_msg_ack {
+	struct ipw_tx_packet header;
+	struct TlSetupRebootMsgAck body;
+};
+
+/* This handles the actual initialization of the card */
+static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
+{
+	struct ipw_setup_config_packet *config_packet;
+	struct ipw_setup_config_done_packet *config_done_packet;
+	struct ipw_setup_open_packet *open_packet;
+	struct ipw_setup_info_packet *info_packet;
+	int port;
+	unsigned int channel_idx;
+
+	/* generate config packet */
+	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
+		config_packet = alloc_ctrl_packet(
+				sizeof(struct ipw_setup_config_packet),
+				ADDR_SETUP_PROT,
+				TL_PROTOCOLID_SETUP,
+				TL_SETUP_SIGNO_CONFIG_MSG);
+		if (!config_packet)
+			goto exit_nomem;
+		config_packet->header.length = sizeof(struct tl_setup_config_msg);
+		config_packet->body.port_no = port;
+		config_packet->body.prio_data = PRIO_DATA;
+		config_packet->body.prio_ctrl = PRIO_CTRL;
+		send_packet(hw, PRIO_SETUP, &config_packet->header);
+	}
+	config_done_packet = alloc_ctrl_packet(
+			sizeof(struct ipw_setup_config_done_packet),
+			ADDR_SETUP_PROT,
+			TL_PROTOCOLID_SETUP,
+			TL_SETUP_SIGNO_CONFIG_DONE_MSG);
+	if (!config_done_packet)
+		goto exit_nomem;
+	config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg);
+	send_packet(hw, PRIO_SETUP, &config_done_packet->header);
+
+	/* generate open packet */
+	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
+		open_packet = alloc_ctrl_packet(
+				sizeof(struct ipw_setup_open_packet),
+				ADDR_SETUP_PROT,
+				TL_PROTOCOLID_SETUP,
+				TL_SETUP_SIGNO_OPEN_MSG);
+		if (!open_packet)
+			goto exit_nomem;
+		open_packet->header.length = sizeof(struct tl_setup_open_msg);
+		open_packet->body.port_no = port;
+		send_packet(hw, PRIO_SETUP, &open_packet->header);
+	}
+	for (channel_idx = 0;
+			channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) {
+		int ret;
+
+		ret = set_DTR(hw, PRIO_SETUP, channel_idx,
+			(hw->control_lines[channel_idx] &
+			 IPW_CONTROL_LINE_DTR) != 0);
+		if (ret) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+					": error setting DTR (%d)\n", ret);
+			return;
+		}
+
+		set_RTS(hw, PRIO_SETUP, channel_idx,
+			(hw->control_lines [channel_idx] &
+			 IPW_CONTROL_LINE_RTS) != 0);
+		if (ret) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+					": error setting RTS (%d)\n", ret);
+			return;
+		}
+	}
+	/*
+	 * For NDIS we assume that we are using sync PPP frames, for COM async.
+	 * This driver uses NDIS mode too. We don't bother with translation
+	 * from async -> sync PPP.
+	 */
+	info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet),
+			ADDR_SETUP_PROT,
+			TL_PROTOCOLID_SETUP,
+			TL_SETUP_SIGNO_INFO_MSG);
+	if (!info_packet)
+		goto exit_nomem;
+	info_packet->header.length = sizeof(struct tl_setup_info_msg);
+	info_packet->body.driver_type = NDISWAN_DRIVER;
+	info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION;
+	info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION;
+	send_packet(hw, PRIO_SETUP, &info_packet->header);
+
+	/* Initialization is now complete, so we clear the 'to_setup' flag */
+	hw->to_setup = 0;
+
+	return;
+
+exit_nomem:
+	printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+			": not enough memory to alloc control packet\n");
+	hw->to_setup = -1;
+}
+
+static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
+		unsigned char vers_no)
+{
+	del_timer(&hw->setup_timer);
+	hw->initializing = 0;
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n");
+
+	if (vers_no == TL_SETUP_VERSION)
+		__handle_setup_get_version_rsp(hw);
+	else
+		printk(KERN_ERR
+				IPWIRELESS_PCCARD_NAME
+				": invalid hardware version no %u\n",
+				(unsigned int) vers_no);
+}
+
+static void ipw_send_setup_packet(struct ipw_hardware *hw)
+{
+	struct ipw_setup_get_version_query_packet *ver_packet;
+
+	ver_packet = alloc_ctrl_packet(
+			sizeof(struct ipw_setup_get_version_query_packet),
+			ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
+			TL_SETUP_SIGNO_GET_VERSION_QRY);
+	ver_packet->header.length = sizeof(struct tl_setup_get_version_qry);
+
+	/*
+	 * Response is handled in handle_received_SETUP_packet
+	 */
+	send_packet(hw, PRIO_SETUP, &ver_packet->header);
+}
+
+static void handle_received_SETUP_packet(struct ipw_hardware *hw,
+					 unsigned int address,
+					 unsigned char *data, int len,
+					 int is_last)
+{
+	union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data;
+
+	if (address != ADDR_SETUP_PROT) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": setup packet has bad address %d\n", address);
+		return;
+	}
+
+	switch (rx_msg->sig_no) {
+	case TL_SETUP_SIGNO_GET_VERSION_RSP:
+		if (hw->to_setup)
+			handle_setup_get_version_rsp(hw,
+					rx_msg->version_rsp_msg.version);
+		break;
+
+	case TL_SETUP_SIGNO_OPEN_MSG:
+		if (ipwireless_debug) {
+			unsigned int channel_idx = rx_msg->open_msg.port_no - 1;
+
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": OPEN_MSG [channel %u] reply received\n",
+			       channel_idx);
+		}
+		break;
+
+	case TL_SETUP_SIGNO_INFO_MSG_ACK:
+		if (ipwireless_debug)
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+			       ": card successfully configured as NDISWAN\n");
+		break;
+
+	case TL_SETUP_SIGNO_REBOOT_MSG:
+		if (hw->to_setup)
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+			       ": Setup not completed - ignoring reboot msg\n");
+		else {
+			struct ipw_setup_reboot_msg_ack *packet;
+
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+			       ": Acknowledging REBOOT message\n");
+			packet = alloc_ctrl_packet(
+					sizeof(struct ipw_setup_reboot_msg_ack),
+					ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
+					TL_SETUP_SIGNO_REBOOT_MSG_ACK);
+			packet->header.length =
+				sizeof(struct TlSetupRebootMsgAck);
+			send_packet(hw, PRIO_SETUP, &packet->header);
+			if (hw->reboot_callback)
+				hw->reboot_callback(hw->reboot_callback_data);
+		}
+		break;
+
+	default:
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": unknown setup message %u received\n",
+		       (unsigned int) rx_msg->sig_no);
+	}
+}
+
+static void do_close_hardware(struct ipw_hardware *hw)
+{
+	unsigned int irqn;
+
+	if (hw->hw_version == HW_VERSION_1) {
+		/* Disable TX and RX interrupts. */
+		outw(0, hw->base_port + IOIER);
+
+		/* Acknowledge any outstanding interrupt requests */
+		irqn = inw(hw->base_port + IOIR);
+		if (irqn & IR_TXINTR)
+			outw(IR_TXINTR, hw->base_port + IOIR);
+		if (irqn & IR_RXINTR)
+			outw(IR_RXINTR, hw->base_port + IOIR);
+
+		synchronize_irq(hw->irq);
+	}
+}
+
+struct ipw_hardware *ipwireless_hardware_create(void)
+{
+	int i;
+	struct ipw_hardware *hw =
+		kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL);
+
+	if (!hw)
+		return NULL;
+
+	hw->irq = -1;
+	hw->initializing = 1;
+	hw->tx_ready = 1;
+	hw->rx_bytes_queued = 0;
+	hw->rx_pool_size = 0;
+	hw->last_memtx_serial = (unsigned short) 0xffff;
+	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
+		INIT_LIST_HEAD(&hw->tx_queue[i]);
+
+	INIT_LIST_HEAD(&hw->rx_queue);
+	INIT_LIST_HEAD(&hw->rx_pool);
+	spin_lock_init(&hw->spinlock);
+	tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
+	INIT_WORK(&hw->work_rx, ipw_receive_data_work);
+	setup_timer(&hw->setup_timer, ipwireless_setup_timer,
+			(unsigned long) hw);
+
+	return hw;
+}
+
+void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
+		unsigned int base_port,
+		void __iomem *attr_memory,
+		void __iomem *common_memory,
+		int is_v2_card,
+		void (*reboot_callback) (void *data),
+		void *reboot_callback_data)
+{
+	if (hw->removed) {
+		hw->removed = 0;
+		enable_irq(hw->irq);
+	}
+	hw->base_port = base_port;
+	hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1;
+	hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2;
+	hw->memregs_CCR = (struct MEMCCR __iomem *)
+			((unsigned short __iomem *) attr_memory + 0x200);
+	hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
+	hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new;
+	hw->reboot_callback = reboot_callback;
+	hw->reboot_callback_data = reboot_callback_data;
+}
+
+void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw)
+{
+	hw->initializing = 1;
+	hw->init_loops = 0;
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+	       ": waiting for card to start up...\n");
+	ipwireless_setup_timer((unsigned long) hw);
+}
+
+static void ipwireless_setup_timer(unsigned long data)
+{
+	struct ipw_hardware *hw = (struct ipw_hardware *) data;
+
+	hw->init_loops++;
+
+	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY &&
+			hw->hw_version == HW_VERSION_2 &&
+			hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+				": failed to startup using TX2, trying TX\n");
+
+		hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old;
+		hw->init_loops = 0;
+	}
+	/* Give up after a certain number of retries */
+	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": card failed to start up!\n");
+		hw->initializing = 0;
+	} else {
+		/* Do not attempt to write to the board if it is not present. */
+		if (is_card_present(hw)) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&hw->spinlock, flags);
+			hw->to_setup = 1;
+			hw->tx_ready = 1;
+			spin_unlock_irqrestore(&hw->spinlock, flags);
+			tasklet_schedule(&hw->tasklet);
+		}
+
+		mod_timer(&hw->setup_timer,
+			jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO));
+	}
+}
+
+/*
+ * Stop any interrupts from executing so that, once this function returns,
+ * other layers of the driver can be sure they won't get any more callbacks.
+ * Thus must be called on a proper process context.
+ */
+void ipwireless_stop_interrupts(struct ipw_hardware *hw)
+{
+	if (!hw->shutting_down) {
+		/* Tell everyone we are going down. */
+		hw->shutting_down = 1;
+		del_timer(&hw->setup_timer);
+
+		/* Prevent the hardware from sending any more interrupts */
+		do_close_hardware(hw);
+	}
+}
+
+void ipwireless_hardware_free(struct ipw_hardware *hw)
+{
+	int i;
+	struct ipw_rx_packet *rp, *rq;
+	struct ipw_tx_packet *tp, *tq;
+
+	ipwireless_stop_interrupts(hw);
+
+	flush_scheduled_work();
+
+	for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
+		if (hw->packet_assembler[i] != NULL)
+			kfree(hw->packet_assembler[i]);
+
+	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
+		list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) {
+			list_del(&tp->queue);
+			kfree(tp);
+		}
+
+	list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) {
+		list_del(&rp->queue);
+		kfree(rp);
+	}
+
+	list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) {
+		list_del(&rp->queue);
+		kfree(rp);
+	}
+	kfree(hw);
+}
+
+/*
+ * Associate the specified network with this hardware, so it will receive events
+ * from it.
+ */
+void ipwireless_associate_network(struct ipw_hardware *hw,
+				  struct ipw_network *network)
+{
+	hw->network = network;
+}
diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h
new file mode 100644
index 0000000..c83190f
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/hardware.h
@@ -0,0 +1,64 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_HARDWARE_H_
+#define _IPWIRELESS_CS_HARDWARE_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#define IPW_CONTROL_LINE_CTS 0x0001
+#define IPW_CONTROL_LINE_DCD 0x0002
+#define IPW_CONTROL_LINE_DSR 0x0004
+#define IPW_CONTROL_LINE_RI  0x0008
+#define IPW_CONTROL_LINE_DTR 0x0010
+#define IPW_CONTROL_LINE_RTS 0x0020
+
+struct ipw_hardware;
+struct ipw_network;
+
+struct ipw_hardware *ipwireless_hardware_create(void);
+void ipwireless_hardware_free(struct ipw_hardware *hw);
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
+		int state);
+int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
+		int state);
+int ipwireless_send_packet(struct ipw_hardware *hw,
+			    unsigned int channel_idx,
+			    unsigned char *data,
+			    unsigned int length,
+			    void (*packet_sent_callback) (void *cb,
+							  unsigned int length),
+			    void *sent_cb_data);
+void ipwireless_associate_network(struct ipw_hardware *hw,
+		struct ipw_network *net);
+void ipwireless_stop_interrupts(struct ipw_hardware *hw);
+void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
+				 unsigned int base_port,
+				 void __iomem *attr_memory,
+				 void __iomem *common_memory,
+				 int is_v2_card,
+				 void (*reboot_cb) (void *data),
+				 void *reboot_cb_data);
+void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
+void ipwireless_sleep(unsigned int tenths);
+int ipwireless_dump_hardware_state(char *p, size_t limit,
+				   struct ipw_hardware *hw);
+
+#endif
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
new file mode 100644
index 0000000..00c7f84
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -0,0 +1,501 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include "hardware.h"
+#include "network.h"
+#include "main.h"
+#include "tty.h"
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/device_id.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cs.h>
+
+static struct pcmcia_device_id ipw_ids[] = {
+	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
+	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
+	PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
+
+static void ipwireless_detach(struct pcmcia_device *link);
+
+/*
+ * Module params
+ */
+/* Debug mode: more verbose, print sent/recv bytes */
+int ipwireless_debug;
+int ipwireless_loopback;
+int ipwireless_out_queue = 1;
+
+module_param_named(debug, ipwireless_debug, int, 0);
+module_param_named(loopback, ipwireless_loopback, int, 0);
+module_param_named(out_queue, ipwireless_out_queue, int, 0);
+MODULE_PARM_DESC(debug, "switch on debug messages [0]");
+MODULE_PARM_DESC(loopback,
+		"debug: enable ras_raw channel [0]");
+MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]");
+
+/* Executes in process context. */
+static void signalled_reboot_work(struct work_struct *work_reboot)
+{
+	struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
+			work_reboot);
+	struct pcmcia_device *link = ipw->link;
+	int ret = pccard_reset_card(link->socket);
+
+	if (ret != CS_SUCCESS)
+		cs_error(link, ResetCard, ret);
+}
+
+static void signalled_reboot_callback(void *callback_data)
+{
+	struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
+
+	/* Delegate to process context. */
+	schedule_work(&ipw->work_reboot);
+}
+
+static int config_ipwireless(struct ipw_dev *ipw)
+{
+	struct pcmcia_device *link = ipw->link;
+	int ret;
+	config_info_t conf;
+	tuple_t tuple;
+	unsigned short buf[64];
+	cisparse_t parse;
+	unsigned short cor_value;
+	win_req_t request_attr_memory;
+	win_req_t request_common_memory;
+	memreq_t memreq_attr_memory;
+	memreq_t memreq_common_memory;
+
+	ipw->is_v2_card = 0;
+
+	tuple.Attributes = 0;
+	tuple.TupleData = (cisdata_t *) buf;
+	tuple.TupleDataMax = sizeof(buf);
+	tuple.TupleOffset = 0;
+
+	tuple.DesiredTuple = RETURN_FIRST_TUPLE;
+
+	ret = pcmcia_get_first_tuple(link, &tuple);
+
+	while (ret == 0) {
+		ret = pcmcia_get_tuple_data(link, &tuple);
+
+		if (ret != CS_SUCCESS) {
+			cs_error(link, GetTupleData, ret);
+			goto exit0;
+		}
+		ret = pcmcia_get_next_tuple(link, &tuple);
+	}
+
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+
+	ret = pcmcia_get_first_tuple(link, &tuple);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetFirstTuple, ret);
+		goto exit0;
+	}
+
+	ret = pcmcia_get_tuple_data(link, &tuple);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetTupleData, ret);
+		goto exit0;
+	}
+
+	ret = pcmcia_parse_tuple(link, &tuple, &parse);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, ParseTuple, ret);
+		goto exit0;
+	}
+
+	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+	link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
+	link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
+	link->io.IOAddrLines = 16;
+
+	link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1;
+
+	/* 0x40 causes it to generate level mode interrupts. */
+	/* 0x04 enables IREQ pin. */
+	cor_value = parse.cftable_entry.index | 0x44;
+	link->conf.ConfigIndex = cor_value;
+
+	/* IRQ and I/O settings */
+	tuple.DesiredTuple = CISTPL_CONFIG;
+
+	ret = pcmcia_get_first_tuple(link, &tuple);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetFirstTuple, ret);
+		goto exit0;
+	}
+
+	ret = pcmcia_get_tuple_data(link, &tuple);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetTupleData, ret);
+		goto exit0;
+	}
+
+	ret = pcmcia_parse_tuple(link, &tuple, &parse);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetTupleData, ret);
+		goto exit0;
+	}
+	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+	link->conf.IntType = INT_MEMORY_AND_IO;
+
+	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
+	link->irq.Handler = ipwireless_interrupt;
+	link->irq.Instance = ipw->hardware;
+
+	ret = pcmcia_request_io(link, &link->io);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, RequestIO, ret);
+		goto exit0;
+	}
+
+	/* memory settings */
+
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+
+	ret = pcmcia_get_first_tuple(link, &tuple);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetFirstTuple, ret);
+		goto exit1;
+	}
+
+	ret = pcmcia_get_tuple_data(link, &tuple);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetTupleData, ret);
+		goto exit1;
+	}
+
+	ret = pcmcia_parse_tuple(link, &tuple, &parse);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, ParseTuple, ret);
+		goto exit1;
+	}
+
+	if (parse.cftable_entry.mem.nwin > 0) {
+		request_common_memory.Attributes =
+			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+		request_common_memory.Base =
+			parse.cftable_entry.mem.win[0].host_addr;
+		request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
+		if (request_common_memory.Size < 0x1000)
+			request_common_memory.Size = 0x1000;
+		request_common_memory.AccessSpeed = 0;
+
+		ret = pcmcia_request_window(&link, &request_common_memory,
+				&ipw->handle_common_memory);
+
+		if (ret != CS_SUCCESS) {
+			cs_error(link, RequestWindow, ret);
+			goto exit1;
+		}
+
+		memreq_common_memory.CardOffset =
+			parse.cftable_entry.mem.win[0].card_addr;
+		memreq_common_memory.Page = 0;
+
+		ret = pcmcia_map_mem_page(ipw->handle_common_memory,
+				&memreq_common_memory);
+
+		if (ret != CS_SUCCESS) {
+			cs_error(link, MapMemPage, ret);
+			goto exit1;
+		}
+
+		ipw->is_v2_card =
+			parse.cftable_entry.mem.win[0].len == 0x100;
+
+		ipw->common_memory = ioremap(request_common_memory.Base,
+				request_common_memory.Size);
+
+		request_attr_memory.Attributes =
+			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
+		request_attr_memory.Base = 0;
+		request_attr_memory.Size = 0;	/* this used to be 0x1000 */
+		request_attr_memory.AccessSpeed = 0;
+
+		ret = pcmcia_request_window(&link, &request_attr_memory,
+				&ipw->handle_attr_memory);
+
+		if (ret != CS_SUCCESS) {
+			cs_error(link, RequestWindow, ret);
+			goto exit2;
+		}
+
+		memreq_attr_memory.CardOffset = 0;
+		memreq_attr_memory.Page = 0;
+
+		ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
+				&memreq_attr_memory);
+
+		if (ret != CS_SUCCESS) {
+			cs_error(link, MapMemPage, ret);
+			goto exit2;
+		}
+
+		ipw->attr_memory = ioremap(request_attr_memory.Base,
+				request_attr_memory.Size);
+	}
+
+	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
+
+	ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1,
+				    ipw->attr_memory, ipw->common_memory,
+				    ipw->is_v2_card, signalled_reboot_callback,
+				    ipw);
+
+	ret = pcmcia_request_irq(link, &link->irq);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, RequestIRQ, ret);
+		goto exit3;
+	}
+
+	/* Look up current Vcc */
+
+	ret = pcmcia_get_configuration_info(link, &conf);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, GetConfigurationInfo, ret);
+		goto exit4;
+	}
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
+			ipw->is_v2_card ? "V2/V3" : "V1");
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			": I/O ports 0x%04x-0x%04x, irq %d\n",
+			(unsigned int) link->io.BasePort1,
+			(unsigned int) (link->io.BasePort1 +
+				link->io.NumPorts1 - 1),
+			(unsigned int) link->irq.AssignedIRQ);
+	if (ipw->attr_memory && ipw->common_memory)
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+				": attr memory 0x%08lx-0x%08lx, "
+				"common memory 0x%08lx-0x%08lx\n",
+				request_attr_memory.Base,
+				request_attr_memory.Base
+				+ request_attr_memory.Size - 1,
+				request_common_memory.Base,
+				request_common_memory.Base
+				+ request_common_memory.Size - 1);
+
+	ipw->network = ipwireless_network_create(ipw->hardware);
+	if (!ipw->network)
+		goto exit3;
+
+	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,
+			ipw->nodes);
+	if (!ipw->tty)
+		goto exit3;
+
+	ipwireless_init_hardware_v2_v3(ipw->hardware);
+
+	/*
+	 * Do the RequestConfiguration last, because it enables interrupts.
+	 * Then we don't get any interrupts before we're ready for them.
+	 */
+	ret = pcmcia_request_configuration(link, &link->conf);
+
+	if (ret != CS_SUCCESS) {
+		cs_error(link, RequestConfiguration, ret);
+		goto exit4;
+	}
+
+	link->dev_node = &ipw->nodes[0];
+
+	return 0;
+
+exit4:
+	pcmcia_disable_device(link);
+exit3:
+	if (ipw->attr_memory) {
+		iounmap(ipw->attr_memory);
+		pcmcia_release_window(ipw->handle_attr_memory);
+		pcmcia_disable_device(link);
+	}
+exit2:
+	if (ipw->common_memory) {
+		iounmap(ipw->common_memory);
+		pcmcia_release_window(ipw->handle_common_memory);
+	}
+exit1:
+	pcmcia_disable_device(link);
+exit0:
+	return -1;
+}
+
+static void release_ipwireless(struct ipw_dev *ipw)
+{
+	struct pcmcia_device *link = ipw->link;
+
+	pcmcia_disable_device(link);
+
+	if (ipw->common_memory)
+		iounmap(ipw->common_memory);
+	if (ipw->attr_memory)
+		iounmap(ipw->attr_memory);
+	if (ipw->common_memory)
+		pcmcia_release_window(ipw->handle_common_memory);
+	if (ipw->attr_memory)
+		pcmcia_release_window(ipw->handle_attr_memory);
+	pcmcia_disable_device(link);
+}
+
+/*
+ * ipwireless_attach() creates an "instance" of the driver, allocating
+ * local data structures for one device (one interface).  The device
+ * is registered with Card Services.
+ *
+ * The pcmcia_device structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a
+ * card insertion event.
+ */
+static int ipwireless_attach(struct pcmcia_device *link)
+{
+	struct ipw_dev *ipw;
+	int ret;
+
+	ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
+	if (!ipw)
+		return -ENOMEM;
+
+	ipw->link = link;
+	link->priv = ipw;
+	link->irq.Instance = ipw;
+
+	/* Link this device into our device list. */
+	link->dev_node = &ipw->nodes[0];
+
+	ipw->hardware = ipwireless_hardware_create();
+	if (!ipw->hardware) {
+		kfree(ipw);
+		return -ENOMEM;
+	}
+	/* RegisterClient will call config_ipwireless */
+
+	ret = config_ipwireless(ipw);
+
+	if (ret != 0) {
+		cs_error(link, RegisterClient, ret);
+		ipwireless_detach(link);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * This deletes a driver "instance".  The device is de-registered with
+ * Card Services.  If it has been released, all local data structures
+ * are freed.  Otherwise, the structures will be freed when the device
+ * is released.
+ */
+static void ipwireless_detach(struct pcmcia_device *link)
+{
+	struct ipw_dev *ipw = link->priv;
+
+	release_ipwireless(ipw);
+
+	/* Break the link with Card Services */
+	if (link)
+		pcmcia_disable_device(link);
+
+	if (ipw->tty != NULL)
+		ipwireless_tty_free(ipw->tty);
+	if (ipw->network != NULL)
+		ipwireless_network_free(ipw->network);
+	if (ipw->hardware != NULL)
+		ipwireless_hardware_free(ipw->hardware);
+	kfree(ipw);
+}
+
+static struct pcmcia_driver me = {
+	.owner		= THIS_MODULE,
+	.probe          = ipwireless_attach,
+	.remove         = ipwireless_detach,
+	.drv = { .name  = IPWIRELESS_PCCARD_NAME },
+	.id_table       = ipw_ids
+};
+
+/*
+ * Module insertion : initialisation of the module.
+ * Register the card with cardmgr...
+ */
+static int __init init_ipwireless(void)
+{
+	int ret;
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
+	       IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n");
+
+	ret = ipwireless_tty_init();
+	if (ret != 0)
+		return ret;
+
+	ret = pcmcia_register_driver(&me);
+	if (ret != 0)
+		ipwireless_tty_release();
+
+	return ret;
+}
+
+/*
+ * Module removal
+ */
+static void __exit exit_ipwireless(void)
+{
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
+			IPWIRELESS_PCMCIA_VERSION " removed\n");
+
+	pcmcia_unregister_driver(&me);
+	ipwireless_tty_release();
+}
+
+module_init(init_ipwireless);
+module_exit(exit_ipwireless);
+
+MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
+MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
new file mode 100644
index 0000000..1bfdcc8
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -0,0 +1,70 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_H_
+#define _IPWIRELESS_CS_H_
+
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include "hardware.h"
+
+#define IPWIRELESS_PCCARD_NAME		"ipwireless"
+#define IPWIRELESS_PCMCIA_VERSION	"1.1"
+#define IPWIRELESS_PCMCIA_AUTHOR        \
+	"Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba"
+
+#define IPWIRELESS_TX_QUEUE_SIZE  262144
+#define IPWIRELESS_RX_QUEUE_SIZE  262144
+
+#define IPWIRELESS_STATE_DEBUG
+
+struct ipw_hardware;
+struct ipw_network;
+struct ipw_tty;
+
+struct ipw_dev {
+	struct pcmcia_device *link;
+	int is_v2_card;
+	window_handle_t handle_attr_memory;
+	void __iomem *attr_memory;
+	window_handle_t handle_common_memory;
+	void __iomem *common_memory;
+	dev_node_t nodes[2];
+	/* Reference to attribute memory, containing CIS data */
+	void *attribute_memory;
+
+	/* Hardware context */
+	struct ipw_hardware *hardware;
+	/* Network layer context */
+	struct ipw_network *network;
+	/* TTY device context */
+	struct ipw_tty *tty;
+	struct work_struct work_reboot;
+};
+
+/* Module parametres */
+extern int ipwireless_debug;
+extern int ipwireless_loopback;
+extern int ipwireless_out_queue;
+
+#endif
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c
new file mode 100644
index 0000000..ff35230
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/network.c
@@ -0,0 +1,512 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/skbuff.h>
+
+#include "network.h"
+#include "hardware.h"
+#include "main.h"
+#include "tty.h"
+
+#define MAX_OUTGOING_PACKETS_QUEUED   ipwireless_out_queue
+#define MAX_ASSOCIATED_TTYS 2
+
+#define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+struct ipw_network {
+	/* Hardware context, used for calls to hardware layer. */
+	struct ipw_hardware *hardware;
+	/* Context for kernel 'generic_ppp' functionality */
+	struct ppp_channel *ppp_channel;
+	/* tty context connected with IPW console */
+	struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
+	/* True if ppp needs waking up once we're ready to xmit */
+	int ppp_blocked;
+	/* Number of packets queued up in hardware module. */
+	int outgoing_packets_queued;
+	/* Spinlock to avoid interrupts during shutdown */
+	spinlock_t spinlock;
+	struct mutex close_lock;
+
+	/* PPP ioctl data, not actually used anywere */
+	unsigned int flags;
+	unsigned int rbits;
+	u32 xaccm[8];
+	u32 raccm;
+	int mru;
+
+	int shutting_down;
+	unsigned int ras_control_lines;
+
+	struct work_struct work_go_online;
+	struct work_struct work_go_offline;
+};
+
+
+#ifdef IPWIRELESS_STATE_DEBUG
+int ipwireless_dump_network_state(char *p, size_t limit,
+				  struct ipw_network *network)
+{
+	return snprintf(p, limit,
+			"debug: ppp_blocked=%d\n"
+			"debug: outgoing_packets_queued=%d\n"
+			"debug: network.shutting_down=%d\n",
+			network->ppp_blocked,
+			network->outgoing_packets_queued,
+			network->shutting_down);
+}
+#endif
+
+static void notify_packet_sent(void *callback_data, unsigned int packet_length)
+{
+	struct ipw_network *network = callback_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->spinlock, flags);
+	network->outgoing_packets_queued--;
+	if (network->ppp_channel != NULL) {
+		if (network->ppp_blocked) {
+			network->ppp_blocked = 0;
+			spin_unlock_irqrestore(&network->spinlock, flags);
+			ppp_output_wakeup(network->ppp_channel);
+			if (ipwireless_debug)
+				printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+				       ": ppp unblocked\n");
+		} else
+			spin_unlock_irqrestore(&network->spinlock, flags);
+	} else
+		spin_unlock_irqrestore(&network->spinlock, flags);
+}
+
+/*
+ * Called by the ppp system when it has a packet to send to the hardware.
+ */
+static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
+				     struct sk_buff *skb)
+{
+	struct ipw_network *network = ppp_channel->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->spinlock, flags);
+	if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) {
+		unsigned char *buf;
+		static unsigned char header[] = {
+			PPP_ALLSTATIONS, /* 0xff */
+			PPP_UI,		 /* 0x03 */
+		};
+		int ret;
+
+		network->outgoing_packets_queued++;
+		spin_unlock_irqrestore(&network->spinlock, flags);
+
+		/*
+		 * If we have the requested amount of headroom in the skb we
+		 * were handed, then we can add the header efficiently.
+		 */
+		if (skb_headroom(skb) >= 2) {
+			memcpy(skb_push(skb, 2), header, 2);
+			ret = ipwireless_send_packet(network->hardware,
+					       IPW_CHANNEL_RAS, skb->data,
+					       skb->len,
+					       notify_packet_sent,
+					       network);
+			if (ret == -1) {
+				skb_pull(skb, 2);
+				return 0;
+			}
+		} else {
+			/* Otherwise (rarely) we do it inefficiently. */
+			buf = kmalloc(skb->len + 2, GFP_ATOMIC);
+			if (!buf)
+				return 0;
+			memcpy(buf + 2, skb->data, skb->len);
+			memcpy(buf, header, 2);
+			ret = ipwireless_send_packet(network->hardware,
+					       IPW_CHANNEL_RAS, buf,
+					       skb->len + 2,
+					       notify_packet_sent,
+					       network);
+			kfree(buf);
+			if (ret == -1)
+				return 0;
+		}
+		kfree_skb(skb);
+		return 1;
+	} else {
+		/*
+		 * Otherwise reject the packet, and flag that the ppp system
+		 * needs to be unblocked once we are ready to send.
+		 */
+		network->ppp_blocked = 1;
+		spin_unlock_irqrestore(&network->spinlock, flags);
+		return 0;
+	}
+}
+
+/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
+static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
+				unsigned int cmd, unsigned long arg)
+{
+	struct ipw_network *network = ppp_channel->private;
+	int err, val;
+	u32 accm[8];
+	int __user *user_arg = (int __user *) arg;
+
+	err = -EFAULT;
+	switch (cmd) {
+	case PPPIOCGFLAGS:
+		val = network->flags | network->rbits;
+		if (put_user(val, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSFLAGS:
+		if (get_user(val, user_arg))
+			break;
+		network->flags = val & ~SC_RCV_BITS;
+		network->rbits = val & SC_RCV_BITS;
+		err = 0;
+		break;
+
+	case PPPIOCGASYNCMAP:
+		if (put_user(network->xaccm[0], user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSASYNCMAP:
+		if (get_user(network->xaccm[0], user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGRASYNCMAP:
+		if (put_user(network->raccm, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSRASYNCMAP:
+		if (get_user(network->raccm, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGXASYNCMAP:
+		if (copy_to_user((void __user *) arg, network->xaccm,
+					sizeof(network->xaccm)))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSXASYNCMAP:
+		if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
+			break;
+		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
+		accm[3] |= 0x60000000U;	/* must escape 0x7d, 0x7e */
+		memcpy(network->xaccm, accm, sizeof(network->xaccm));
+		err = 0;
+		break;
+
+	case PPPIOCGMRU:
+		if (put_user(network->mru, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSMRU:
+		if (get_user(val, user_arg))
+			break;
+		if (val < PPP_MRU)
+			val = PPP_MRU;
+		network->mru = val;
+		err = 0;
+		break;
+
+	default:
+		err = -ENOTTY;
+	}
+
+	return err;
+}
+
+static struct ppp_channel_ops ipwireless_ppp_channel_ops = {
+	.start_xmit = ipwireless_ppp_start_xmit,
+	.ioctl      = ipwireless_ppp_ioctl
+};
+
+static void do_go_online(struct work_struct *work_go_online)
+{
+	struct ipw_network *network =
+		container_of(work_go_online, struct ipw_network,
+				work_go_online);
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->spinlock, flags);
+	if (!network->ppp_channel) {
+		struct ppp_channel *channel;
+
+		spin_unlock_irqrestore(&network->spinlock, flags);
+		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
+		if (!channel) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+					": unable to allocate PPP channel\n");
+			return;
+		}
+		channel->private = network;
+		channel->mtu = 16384;	/* Wild guess */
+		channel->hdrlen = 2;
+		channel->ops = &ipwireless_ppp_channel_ops;
+
+		network->flags = 0;
+		network->rbits = 0;
+		network->mru = PPP_MRU;
+		memset(network->xaccm, 0, sizeof(network->xaccm));
+		network->xaccm[0] = ~0U;
+		network->xaccm[3] = 0x60000000U;
+		network->raccm = ~0U;
+		ppp_register_channel(channel);
+		spin_lock_irqsave(&network->spinlock, flags);
+		network->ppp_channel = channel;
+	}
+	spin_unlock_irqrestore(&network->spinlock, flags);
+}
+
+static void do_go_offline(struct work_struct *work_go_offline)
+{
+	struct ipw_network *network =
+		container_of(work_go_offline, struct ipw_network,
+				work_go_offline);
+	unsigned long flags;
+
+	mutex_lock(&network->close_lock);
+	spin_lock_irqsave(&network->spinlock, flags);
+	if (network->ppp_channel != NULL) {
+		struct ppp_channel *channel = network->ppp_channel;
+
+		network->ppp_channel = NULL;
+		spin_unlock_irqrestore(&network->spinlock, flags);
+		mutex_unlock(&network->close_lock);
+		ppp_unregister_channel(channel);
+	} else {
+		spin_unlock_irqrestore(&network->spinlock, flags);
+		mutex_unlock(&network->close_lock);
+	}
+}
+
+void ipwireless_network_notify_control_line_change(struct ipw_network *network,
+						   unsigned int channel_idx,
+						   unsigned int control_lines,
+						   unsigned int changed_mask)
+{
+	int i;
+
+	if (channel_idx == IPW_CHANNEL_RAS)
+		network->ras_control_lines = control_lines;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
+		struct ipw_tty *tty =
+			network->associated_ttys[channel_idx][i];
+
+		/*
+		 * If it's associated with a tty (other than the RAS channel
+		 * when we're online), then send the data to that tty.  The RAS
+		 * channel's data is handled above - it always goes through
+		 * ppp_generic.
+		 */
+		if (tty)
+			ipwireless_tty_notify_control_line_change(tty,
+								  channel_idx,
+								  control_lines,
+								  changed_mask);
+	}
+}
+
+/*
+ * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
+ * bytes, which are required on sent packet, but not always present on received
+ * packets
+ */
+static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
+					       unsigned int length)
+{
+	struct sk_buff *skb;
+
+	if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
+		length -= 2;
+		data += 2;
+	}
+
+	skb = dev_alloc_skb(length + 4);
+	skb_reserve(skb, 2);
+	memcpy(skb_put(skb, length), data, length);
+
+	return skb;
+}
+
+void ipwireless_network_packet_received(struct ipw_network *network,
+					unsigned int channel_idx,
+					unsigned char *data,
+					unsigned int length)
+{
+	int i;
+	unsigned long flags;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
+		struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
+
+		/*
+		 * If it's associated with a tty (other than the RAS channel
+		 * when we're online), then send the data to that tty.  The RAS
+		 * channel's data is handled above - it always goes through
+		 * ppp_generic.
+		 */
+		if (tty && channel_idx == IPW_CHANNEL_RAS
+				&& (network->ras_control_lines &
+					IPW_CONTROL_LINE_DCD) != 0
+				&& ipwireless_tty_is_modem(tty)) {
+			/*
+			 * If data came in on the RAS channel and this tty is
+			 * the modem tty, and we are online, then we send it to
+			 * the PPP layer.
+			 */
+			mutex_lock(&network->close_lock);
+			spin_lock_irqsave(&network->spinlock, flags);
+			if (network->ppp_channel != NULL) {
+				struct sk_buff *skb;
+
+				spin_unlock_irqrestore(&network->spinlock,
+						flags);
+
+				/* Send the data to the ppp_generic module. */
+				skb = ipw_packet_received_skb(data, length);
+				ppp_input(network->ppp_channel, skb);
+			} else
+				spin_unlock_irqrestore(&network->spinlock,
+						flags);
+			mutex_unlock(&network->close_lock);
+		}
+		/* Otherwise we send it out the tty. */
+		else
+			ipwireless_tty_received(tty, data, length);
+	}
+}
+
+struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
+{
+	struct ipw_network *network =
+		kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
+
+	if (!network)
+		return NULL;
+
+	spin_lock_init(&network->spinlock);
+	mutex_init(&network->close_lock);
+
+	network->hardware = hw;
+
+	INIT_WORK(&network->work_go_online, do_go_online);
+	INIT_WORK(&network->work_go_offline, do_go_offline);
+
+	ipwireless_associate_network(hw, network);
+
+	return network;
+}
+
+void ipwireless_network_free(struct ipw_network *network)
+{
+	network->shutting_down = 1;
+
+	ipwireless_ppp_close(network);
+	flush_scheduled_work();
+
+	ipwireless_stop_interrupts(network->hardware);
+	ipwireless_associate_network(network->hardware, NULL);
+
+	kfree(network);
+}
+
+void ipwireless_associate_network_tty(struct ipw_network *network,
+				      unsigned int channel_idx,
+				      struct ipw_tty *tty)
+{
+	int i;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
+		if (network->associated_ttys[channel_idx][i] == NULL) {
+			network->associated_ttys[channel_idx][i] = tty;
+			break;
+		}
+}
+
+void ipwireless_disassociate_network_ttys(struct ipw_network *network,
+					  unsigned int channel_idx)
+{
+	int i;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
+		network->associated_ttys[channel_idx][i] = NULL;
+}
+
+void ipwireless_ppp_open(struct ipw_network *network)
+{
+	if (ipwireless_debug)
+		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
+	schedule_work(&network->work_go_online);
+}
+
+void ipwireless_ppp_close(struct ipw_network *network)
+{
+	/* Disconnect from the wireless network. */
+	if (ipwireless_debug)
+		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
+	schedule_work(&network->work_go_offline);
+}
+
+int ipwireless_ppp_channel_index(struct ipw_network *network)
+{
+	int ret = -1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->spinlock, flags);
+	if (network->ppp_channel != NULL)
+		ret = ppp_channel_index(network->ppp_channel);
+	spin_unlock_irqrestore(&network->spinlock, flags);
+
+	return ret;
+}
+
+int ipwireless_ppp_unit_number(struct ipw_network *network)
+{
+	int ret = -1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->spinlock, flags);
+	if (network->ppp_channel != NULL)
+		ret = ppp_unit_number(network->ppp_channel);
+	spin_unlock_irqrestore(&network->spinlock, flags);
+
+	return ret;
+}
diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h
new file mode 100644
index 0000000..b0e1e95
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/network.h
@@ -0,0 +1,55 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_NETWORK_H_
+#define _IPWIRELESS_CS_NETWORK_H_
+
+#include <linux/types.h>
+
+struct ipw_network;
+struct ipw_tty;
+struct ipw_hardware;
+
+/* Definitions of the different channels on the PCMCIA UE */
+#define IPW_CHANNEL_RAS      0
+#define IPW_CHANNEL_DIALLER  1
+#define IPW_CHANNEL_CONSOLE  2
+#define NO_OF_IPW_CHANNELS   5
+
+void ipwireless_network_notify_control_line_change(struct ipw_network *net,
+		unsigned int channel_idx, unsigned int control_lines,
+		unsigned int control_mask);
+void ipwireless_network_packet_received(struct ipw_network *net,
+		unsigned int channel_idx, unsigned char *data,
+		unsigned int length);
+struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw);
+void ipwireless_network_free(struct ipw_network *net);
+void ipwireless_associate_network_tty(struct ipw_network *net,
+		unsigned int channel_idx, struct ipw_tty *tty);
+void ipwireless_disassociate_network_ttys(struct ipw_network *net,
+		unsigned int channel_idx);
+
+void ipwireless_ppp_open(struct ipw_network *net);
+
+void ipwireless_ppp_close(struct ipw_network *net);
+int ipwireless_ppp_channel_index(struct ipw_network *net);
+int ipwireless_ppp_unit_number(struct ipw_network *net);
+
+int ipwireless_dump_network_state(char *p, size_t limit,
+				  struct ipw_network *net);
+
+#endif
diff --git a/drivers/char/pcmcia/ipwireless/setup_protocol.h b/drivers/char/pcmcia/ipwireless/setup_protocol.h
new file mode 100644
index 0000000..9d6bcc7
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/setup_protocol.h
@@ -0,0 +1,108 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_
+#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_
+
+/* Version of the setup protocol and transport protocols */
+#define TL_SETUP_VERSION		1
+
+#define TL_SETUP_VERSION_QRY_TMO	1000
+#define TL_SETUP_MAX_VERSION_QRY	30
+
+/* Message numbers 0-9 are obsoleted and must not be reused! */
+#define TL_SETUP_SIGNO_GET_VERSION_QRY	10
+#define TL_SETUP_SIGNO_GET_VERSION_RSP	11
+#define TL_SETUP_SIGNO_CONFIG_MSG	12
+#define TL_SETUP_SIGNO_CONFIG_DONE_MSG	13
+#define TL_SETUP_SIGNO_OPEN_MSG		14
+#define TL_SETUP_SIGNO_CLOSE_MSG	15
+
+#define TL_SETUP_SIGNO_INFO_MSG     20
+#define TL_SETUP_SIGNO_INFO_MSG_ACK 21
+
+#define TL_SETUP_SIGNO_REBOOT_MSG      22
+#define TL_SETUP_SIGNO_REBOOT_MSG_ACK  23
+
+/* Synchronous start-messages */
+struct tl_setup_get_version_qry {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_QRY */
+} __attribute__ ((__packed__));
+
+struct tl_setup_get_version_rsp {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_RSP */
+	unsigned char version;		/* TL_SETUP_VERSION */
+} __attribute__ ((__packed__));
+
+struct tl_setup_config_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_MSG */
+	unsigned char port_no;
+	unsigned char prio_data;
+	unsigned char prio_ctrl;
+} __attribute__ ((__packed__));
+
+struct tl_setup_config_done_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
+} __attribute__ ((__packed__));
+
+/* Asyncronous messages */
+struct tl_setup_open_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_OPEN_MSG */
+	unsigned char port_no;
+} __attribute__ ((__packed__));
+
+struct tl_setup_close_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_CLOSE_MSG */
+	unsigned char port_no;
+} __attribute__ ((__packed__));
+
+/* Driver type  - for use in tl_setup_info_msg.driver_type */
+#define COMM_DRIVER     0
+#define NDISWAN_DRIVER  1
+#define NDISWAN_DRIVER_MAJOR_VERSION  2
+#define NDISWAN_DRIVER_MINOR_VERSION  0
+
+/*
+ * It should not matter when this message comes over as we just store the
+ * results and send the ACK.
+ */
+struct tl_setup_info_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG */
+	unsigned char driver_type;
+	unsigned char major_version;
+	unsigned char minor_version;
+} __attribute__ ((__packed__));
+
+struct tl_setup_info_msgAck {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG_ACK */
+} __attribute__ ((__packed__));
+
+struct TlSetupRebootMsgAck {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_REBOOT_MSG_ACK */
+} __attribute__ ((__packed__));
+
+/* Define a union of all the msgs that the driver can receive from the card.*/
+union ipw_setup_rx_msg {
+	unsigned char sig_no;
+	struct tl_setup_get_version_rsp version_rsp_msg;
+	struct tl_setup_open_msg open_msg;
+	struct tl_setup_close_msg close_msg;
+	struct tl_setup_info_msg InfoMsg;
+	struct tl_setup_info_msgAck info_msg_ack;
+} __attribute__ ((__packed__));
+
+#endif				/* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
new file mode 100644
index 0000000..42f3815
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/tty.c
@@ -0,0 +1,688 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/ppp_defs.h>
+#include <linux/if.h>
+#include <linux/if_ppp.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+
+#include "tty.h"
+#include "network.h"
+#include "hardware.h"
+#include "main.h"
+
+#define IPWIRELESS_PCMCIA_START 	(0)
+#define IPWIRELESS_PCMCIA_MINORS	(24)
+#define IPWIRELESS_PCMCIA_MINOR_RANGE	(8)
+
+#define TTYTYPE_MODEM    (0)
+#define TTYTYPE_MONITOR  (1)
+#define TTYTYPE_RAS_RAW  (2)
+
+struct ipw_tty {
+	int index;
+	struct ipw_hardware *hardware;
+	unsigned int channel_idx;
+	unsigned int secondary_channel_idx;
+	int tty_type;
+	struct ipw_network *network;
+	struct tty_struct *linux_tty;
+	int open_count;
+	unsigned int control_lines;
+	struct mutex ipw_tty_mutex;
+	int tx_bytes_queued;
+	int closing;
+};
+
+static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS];
+
+static struct tty_driver *ipw_tty_driver;
+
+static char *tty_type_name(int tty_type)
+{
+	static char *channel_names[] = {
+		"modem",
+		"monitor",
+		"RAS-raw"
+	};
+
+	return channel_names[tty_type];
+}
+
+static void report_registering(struct ipw_tty *tty)
+{
+	char *iftype = tty_type_name(tty->tty_type);
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+	       ": registering %s device ttyIPWp%d\n", iftype, tty->index);
+}
+
+static void report_deregistering(struct ipw_tty *tty)
+{
+	char *iftype = tty_type_name(tty->tty_type);
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+	       ": deregistering %s device ttyIPWp%d\n", iftype,
+	       tty->index);
+}
+
+static struct ipw_tty *get_tty(int minor)
+{
+	if (minor < ipw_tty_driver->minor_start
+			|| minor >= ipw_tty_driver->minor_start +
+			IPWIRELESS_PCMCIA_MINORS)
+		return NULL;
+	else {
+		int minor_offset = minor - ipw_tty_driver->minor_start;
+
+		/*
+		 * The 'ras_raw' channel is only available when 'loopback' mode
+		 * is enabled.
+		 * Number of minor starts with 16 (_RANGE * _RAS_RAW).
+		 */
+		if (!ipwireless_loopback &&
+				minor_offset >=
+				 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
+			return NULL;
+
+		return ttys[minor_offset];
+	}
+}
+
+static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
+{
+	int minor = linux_tty->index;
+	struct ipw_tty *tty = get_tty(minor);
+
+	if (!tty)
+		return -ENODEV;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+
+	if (tty->closing) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return -ENODEV;
+	}
+	if (tty->open_count == 0)
+		tty->tx_bytes_queued = 0;
+
+	tty->open_count++;
+
+	tty->linux_tty = linux_tty;
+	linux_tty->driver_data = tty;
+	linux_tty->low_latency = 1;
+
+	if (tty->tty_type == TTYTYPE_MODEM)
+		ipwireless_ppp_open(tty->network);
+
+	mutex_unlock(&tty->ipw_tty_mutex);
+
+	return 0;
+}
+
+static void do_ipw_close(struct ipw_tty *tty)
+{
+	tty->open_count--;
+
+	if (tty->open_count == 0) {
+		struct tty_struct *linux_tty = tty->linux_tty;
+
+		if (linux_tty != NULL) {
+			tty->linux_tty = NULL;
+			linux_tty->driver_data = NULL;
+
+			if (tty->tty_type == TTYTYPE_MODEM)
+				ipwireless_ppp_close(tty->network);
+		}
+	}
+}
+
+static void ipw_hangup(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+	if (tty->open_count == 0) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return;
+	}
+
+	do_ipw_close(tty);
+
+	mutex_unlock(&tty->ipw_tty_mutex);
+}
+
+static void ipw_close(struct tty_struct *linux_tty, struct file *filp)
+{
+	ipw_hangup(linux_tty);
+}
+
+/* Take data received from hardware, and send it out the tty */
+void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
+			unsigned int length)
+{
+	struct tty_struct *linux_tty;
+	int work = 0;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+	linux_tty = tty->linux_tty;
+	if (linux_tty == NULL) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return;
+	}
+
+	if (!tty->open_count) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return;
+	}
+	mutex_unlock(&tty->ipw_tty_mutex);
+
+	work = tty_insert_flip_string(linux_tty, data, length);
+
+	if (work != length)
+		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+				": %d chars not inserted to flip buffer!\n",
+				length - work);
+
+	/*
+	 * This may sleep if ->low_latency is set
+	 */
+	if (work)
+		tty_flip_buffer_push(linux_tty);
+}
+
+static void ipw_write_packet_sent_callback(void *callback_data,
+					   unsigned int packet_length)
+{
+	struct ipw_tty *tty = callback_data;
+
+	/*
+	 * Packet has been sent, so we subtract the number of bytes from our
+	 * tally of outstanding TX bytes.
+	 */
+	tty->tx_bytes_queued -= packet_length;
+}
+
+static int ipw_write(struct tty_struct *linux_tty,
+		     const unsigned char *buf, int count)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+	int room, ret;
+
+	if (!tty)
+		return -ENODEV;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+	if (!tty->open_count) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return -EINVAL;
+	}
+
+	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
+	if (room < 0)
+		room = 0;
+	/* Don't allow caller to write any more than we have room for */
+	if (count > room)
+		count = room;
+
+	if (count == 0) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return 0;
+	}
+
+	ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
+			       (unsigned char *) buf, count,
+			       ipw_write_packet_sent_callback, tty);
+	if (ret == -1) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return 0;
+	}
+
+	tty->tx_bytes_queued += count;
+	mutex_unlock(&tty->ipw_tty_mutex);
+
+	return count;
+}
+
+static int ipw_write_room(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+	int room;
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
+	if (room < 0)
+		room = 0;
+
+	return room;
+}
+
+static int ipwireless_get_serial_info(struct ipw_tty *tty,
+				      struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return (-EFAULT);
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = PORT_UNKNOWN;
+	tmp.line = tty->index;
+	tmp.port = 0;
+	tmp.irq = 0;
+	tmp.flags = 0;
+	tmp.baud_base = 115200;
+	tmp.close_delay = 0;
+	tmp.closing_wait = 0;
+	tmp.custom_divisor = 0;
+	tmp.hub6 = 0;
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	return tty->tx_bytes_queued;
+}
+
+static int get_control_lines(struct ipw_tty *tty)
+{
+	unsigned int my = tty->control_lines;
+	unsigned int out = 0;
+
+	if (my & IPW_CONTROL_LINE_RTS)
+		out |= TIOCM_RTS;
+	if (my & IPW_CONTROL_LINE_DTR)
+		out |= TIOCM_DTR;
+	if (my & IPW_CONTROL_LINE_CTS)
+		out |= TIOCM_CTS;
+	if (my & IPW_CONTROL_LINE_DSR)
+		out |= TIOCM_DSR;
+	if (my & IPW_CONTROL_LINE_DCD)
+		out |= TIOCM_CD;
+
+	return out;
+}
+
+static int set_control_lines(struct ipw_tty *tty, unsigned int set,
+			     unsigned int clear)
+{
+	int ret;
+
+	if (set & TIOCM_RTS) {
+		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1);
+		if (ret)
+			return ret;
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_RTS(tty->hardware,
+					  tty->secondary_channel_idx, 1);
+			if (ret)
+				return ret;
+		}
+	}
+	if (set & TIOCM_DTR) {
+		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1);
+		if (ret)
+			return ret;
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_DTR(tty->hardware,
+					  tty->secondary_channel_idx, 1);
+			if (ret)
+				return ret;
+		}
+	}
+	if (clear & TIOCM_RTS) {
+		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0);
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_RTS(tty->hardware,
+					  tty->secondary_channel_idx, 0);
+			if (ret)
+				return ret;
+		}
+	}
+	if (clear & TIOCM_DTR) {
+		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0);
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_DTR(tty->hardware,
+					  tty->secondary_channel_idx, 0);
+			if (ret)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	return get_control_lines(tty);
+}
+
+static int
+ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
+	     unsigned int set, unsigned int clear)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	return set_control_lines(tty, set, clear);
+}
+
+static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		return ipwireless_get_serial_info(tty, (void __user *) arg);
+
+	case TIOCSSERIAL:
+		return 0;	/* Keeps the PCMCIA scripts happy. */
+	}
+
+	if (tty->tty_type == TTYTYPE_MODEM) {
+		switch (cmd) {
+		case PPPIOCGCHAN:
+			{
+				int chan = ipwireless_ppp_channel_index(
+							tty->network);
+
+				if (chan < 0)
+					return -ENODEV;
+				if (put_user(chan, (int __user *) arg))
+					return -EFAULT;
+			}
+			return 0;
+
+		case PPPIOCGUNIT:
+			{
+				int unit = ipwireless_ppp_unit_number(
+						tty->network);
+
+				if (unit < 0)
+					return -ENODEV;
+				if (put_user(unit, (int __user *) arg))
+					return -EFAULT;
+			}
+			return 0;
+
+		case TCGETS:
+		case TCGETA:
+			return n_tty_ioctl(linux_tty, file, cmd, arg);
+
+		case TCFLSH:
+			return n_tty_ioctl(linux_tty, file, cmd, arg);
+
+		case FIONREAD:
+			{
+				int val = 0;
+
+				if (put_user(val, (int __user *) arg))
+					return -EFAULT;
+			}
+			return 0;
+		}
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int add_tty(dev_node_t *nodesp, int j,
+		    struct ipw_hardware *hardware,
+		    struct ipw_network *network, int channel_idx,
+		    int secondary_channel_idx, int tty_type)
+{
+	ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL);
+	if (!ttys[j])
+		return -ENOMEM;
+	ttys[j]->index = j;
+	ttys[j]->hardware = hardware;
+	ttys[j]->channel_idx = channel_idx;
+	ttys[j]->secondary_channel_idx = secondary_channel_idx;
+	ttys[j]->network = network;
+	ttys[j]->tty_type = tty_type;
+	mutex_init(&ttys[j]->ipw_tty_mutex);
+
+	tty_register_device(ipw_tty_driver, j, NULL);
+	ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
+
+	if (secondary_channel_idx != -1)
+		ipwireless_associate_network_tty(network,
+						 secondary_channel_idx,
+						 ttys[j]);
+	if (nodesp != NULL) {
+		sprintf(nodesp->dev_name, "ttyIPWp%d", j);
+		nodesp->major = ipw_tty_driver->major;
+		nodesp->minor = j + ipw_tty_driver->minor_start;
+	}
+	if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j])
+		report_registering(ttys[j]);
+	return 0;
+}
+
+struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware,
+				      struct ipw_network *network,
+				      dev_node_t *nodes)
+{
+	int i, j;
+
+	for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) {
+		int allfree = 1;
+
+		for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
+				j += IPWIRELESS_PCMCIA_MINOR_RANGE)
+			if (ttys[j] != NULL) {
+				allfree = 0;
+				break;
+			}
+
+		if (allfree) {
+			j = i;
+
+			if (add_tty(&nodes[0], j, hardware, network,
+					IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
+					TTYTYPE_MODEM))
+				return NULL;
+
+			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
+			if (add_tty(&nodes[1], j, hardware, network,
+					IPW_CHANNEL_DIALLER, -1,
+					TTYTYPE_MONITOR))
+				return NULL;
+
+			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
+			if (add_tty(NULL, j, hardware, network,
+					IPW_CHANNEL_RAS, -1,
+					TTYTYPE_RAS_RAW))
+				return NULL;
+
+			nodes[0].next = &nodes[1];
+			nodes[1].next = NULL;
+
+			return ttys[i];
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Must be called before ipwireless_network_free().
+ */
+void ipwireless_tty_free(struct ipw_tty *tty)
+{
+	int j;
+	struct ipw_network *network = ttys[tty->index]->network;
+
+	for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS;
+			j += IPWIRELESS_PCMCIA_MINOR_RANGE) {
+		struct ipw_tty *ttyj = ttys[j];
+
+		if (ttyj) {
+			mutex_lock(&ttyj->ipw_tty_mutex);
+			if (get_tty(j + ipw_tty_driver->minor_start) == ttyj)
+				report_deregistering(ttyj);
+			ttyj->closing = 1;
+			if (ttyj->linux_tty != NULL) {
+				mutex_unlock(&ttyj->ipw_tty_mutex);
+				tty_hangup(ttyj->linux_tty);
+				/* Wait till the tty_hangup has completed */
+				flush_scheduled_work();
+				mutex_lock(&ttyj->ipw_tty_mutex);
+			}
+			while (ttyj->open_count)
+				do_ipw_close(ttyj);
+			ipwireless_disassociate_network_ttys(network,
+							     ttyj->channel_idx);
+			tty_unregister_device(ipw_tty_driver, j);
+			ttys[j] = NULL;
+			mutex_unlock(&ttyj->ipw_tty_mutex);
+			kfree(ttyj);
+		}
+	}
+}
+
+static struct tty_operations tty_ops = {
+	.open = ipw_open,
+	.close = ipw_close,
+	.hangup = ipw_hangup,
+	.write = ipw_write,
+	.write_room = ipw_write_room,
+	.ioctl = ipw_ioctl,
+	.chars_in_buffer = ipw_chars_in_buffer,
+	.tiocmget = ipw_tiocmget,
+	.tiocmset = ipw_tiocmset,
+};
+
+int ipwireless_tty_init(void)
+{
+	int result;
+
+	ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
+	if (!ipw_tty_driver)
+		return -ENOMEM;
+
+	ipw_tty_driver->owner = THIS_MODULE;
+	ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
+	ipw_tty_driver->name = "ttyIPWp";
+	ipw_tty_driver->major = 0;
+	ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
+	ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	ipw_tty_driver->init_termios = tty_std_termios;
+	ipw_tty_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	ipw_tty_driver->init_termios.c_ispeed = 9600;
+	ipw_tty_driver->init_termios.c_ospeed = 9600;
+	tty_set_operations(ipw_tty_driver, &tty_ops);
+	result = tty_register_driver(ipw_tty_driver);
+	if (result) {
+		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+		       ": failed to register tty driver\n");
+		put_tty_driver(ipw_tty_driver);
+		return result;
+	}
+
+	return 0;
+}
+
+void ipwireless_tty_release(void)
+{
+	int ret;
+
+	ret = tty_unregister_driver(ipw_tty_driver);
+	put_tty_driver(ipw_tty_driver);
+	if (ret != 0)
+		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+			": tty_unregister_driver failed with code %d\n", ret);
+}
+
+int ipwireless_tty_is_modem(struct ipw_tty *tty)
+{
+	return tty->tty_type == TTYTYPE_MODEM;
+}
+
+void
+ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
+					  unsigned int channel_idx,
+					  unsigned int control_lines,
+					  unsigned int changed_mask)
+{
+	unsigned int old_control_lines = tty->control_lines;
+
+	tty->control_lines = (tty->control_lines & ~changed_mask)
+		| (control_lines & changed_mask);
+
+	/*
+	 * If DCD is de-asserted, we close the tty so pppd can tell that we
+	 * have gone offline.
+	 */
+	if ((old_control_lines & IPW_CONTROL_LINE_DCD)
+			&& !(tty->control_lines & IPW_CONTROL_LINE_DCD)
+			&& tty->linux_tty) {
+		tty_hangup(tty->linux_tty);
+	}
+}
+
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h
new file mode 100644
index 0000000..b0deb91
--- /dev/null
+++ b/drivers/char/pcmcia/ipwireless/tty.h
@@ -0,0 +1,48 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_TTY_H_
+#define _IPWIRELESS_CS_TTY_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+struct ipw_tty;
+struct ipw_network;
+struct ipw_hardware;
+
+int ipwireless_tty_init(void);
+void ipwireless_tty_release(void);
+
+struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw,
+				      struct ipw_network *net,
+				      dev_node_t *nodes);
+void ipwireless_tty_free(struct ipw_tty *tty);
+void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
+			     unsigned int length);
+int ipwireless_tty_is_modem(struct ipw_tty *tty);
+void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
+					       unsigned int channel_idx,
+					       unsigned int control_lines,
+					       unsigned int changed_mask);
+
+#endif
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index e0bade7..1412d7b 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -43,18 +43,12 @@
  *	We have to be cautious here. We have seen BIOSes with DMI pointers
  *	pointing to completely the wrong place for example
  */
-static int __init dmi_table(u32 base, int len, int num,
-			    void (*decode)(const struct dmi_header *))
+static void dmi_table(u8 *buf, int len, int num,
+		      void (*decode)(const struct dmi_header *))
 {
-	u8 *buf, *data;
+	u8 *data = buf;
 	int i = 0;
 
-	buf = dmi_ioremap(base, len);
-	if (buf == NULL)
-		return -1;
-
-	data = buf;
-
 	/*
 	 *	Stop when we see all the items the table claimed to have
 	 *	OR we run off the end of the table (also happens)
@@ -75,7 +69,23 @@
 		data += 2;
 		i++;
 	}
-	dmi_iounmap(buf, len);
+}
+
+static u32 dmi_base;
+static u16 dmi_len;
+static u16 dmi_num;
+
+static int __init dmi_walk_early(void (*decode)(const struct dmi_header *))
+{
+	u8 *buf;
+
+	buf = dmi_ioremap(dmi_base, dmi_len);
+	if (buf == NULL)
+		return -1;
+
+	dmi_table(buf, dmi_len, dmi_num, decode);
+
+	dmi_iounmap(buf, dmi_len);
 	return 0;
 }
 
@@ -291,9 +301,9 @@
 
 	memcpy_fromio(buf, p, 15);
 	if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
-		u16 num = (buf[13] << 8) | buf[12];
-		u16 len = (buf[7] << 8) | buf[6];
-		u32 base = (buf[11] << 24) | (buf[10] << 16) |
+		dmi_num = (buf[13] << 8) | buf[12];
+		dmi_len = (buf[7] << 8) | buf[6];
+		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
 			(buf[9] << 8) | buf[8];
 
 		/*
@@ -305,7 +315,7 @@
 			       buf[14] >> 4, buf[14] & 0xF);
 		else
 			printk(KERN_INFO "DMI present.\n");
-		if (dmi_table(base,len, num, dmi_decode) == 0)
+		if (dmi_walk_early(dmi_decode) == 0)
 			return 0;
 	}
 	return 1;
@@ -489,3 +499,27 @@
 
 	return year;
 }
+
+/**
+ *	dmi_walk - Walk the DMI table and get called back for every record
+ *	@decode: Callback function
+ *
+ *	Returns -1 when the DMI table can't be reached, 0 on success.
+ */
+int dmi_walk(void (*decode)(const struct dmi_header *))
+{
+	u8 *buf;
+
+	if (!dmi_available)
+		return -1;
+
+	buf = ioremap(dmi_base, dmi_len);
+	if (buf == NULL)
+		return -1;
+
+	dmi_table(buf, dmi_len, dmi_num, decode);
+
+	iounmap(buf);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dmi_walk);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index a0445be..410ffe4 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -433,12 +433,12 @@
 	  will be called lm85.
 
 config SENSORS_LM87
-	tristate "National Semiconductor LM87"
+	tristate "National Semiconductor LM87 and compatibles"
 	depends on I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for National Semiconductor LM87
-	  sensor chips.
+	  and Analog Devices ADM1024 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm87.
@@ -588,6 +588,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47b397.
 
+config SENSORS_ADS7828
+	tristate "Texas Instruments ADS7828"
+	depends on I2C
+	help
+	  If you say yes here you get support for Texas Instruments ADS7828
+	  12-bit 8-channel ADC device.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ads7828.
+
 config SENSORS_THMC50
 	tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
 	depends on I2C && EXPERIMENTAL
@@ -631,13 +641,13 @@
 	  will be called vt8231.
 
 config SENSORS_W83781D
-	tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
+	tristate "Winbond W83781D, W83782D, W83783S, Asus AS99127F"
 	depends on I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W8378x series
-	  of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
-	  and the similar Asus AS99127F.
+	  of sensor chips: the W83781D, W83782D and W83783S, and the similar
+	  Asus AS99127F.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83781d.
@@ -683,6 +693,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83l785ts.
 
+config SENSORS_W83L786NG
+	tristate "Winbond W83L786NG, W83L786NR"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Winbond W83L786NG
+	  and W83L786NR sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called w83l786ng.
+
 config SENSORS_W83627HF
 	tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
 	select HWMON_VID
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 55595f6..8241613 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_SENSORS_ADM1029)	+= adm1029.o
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
+obj-$(CONFIG_SENSORS_ADS7828)	+= ads7828.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
@@ -68,6 +69,7 @@
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
 obj-$(CONFIG_SENSORS_W83627EHF)	+= w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
+obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
 
 ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index d9f04ce..ed33fdd 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -528,6 +528,7 @@
 		{ "AUX1 Fan",		33, 2, 60, 1, 0 },
 		{ "AUX2 Fan",		35, 2, 60, 1, 0 },
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
+		{ "AUX4 Fan",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	{ 0x001B, "unknown", {
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index ebdc6d7..b96be77 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -115,7 +115,6 @@
 	.driver = {
 		.name	= "adm1021",
 	},
-	.id		= I2C_DRIVERID_ADM1021,
 	.attach_adapter	= adm1021_attach_adapter,
 	.detach_client	= adm1021_detach_client,
 };
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 041ecb0..e96c372 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -51,6 +51,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
@@ -74,7 +75,7 @@
  */
 
 #define ADM1025_REG_MAN_ID		0x3E
-#define ADM1025_REG_CHIP_ID 		0x3F
+#define ADM1025_REG_CHIP_ID		0x3F
 #define ADM1025_REG_CONFIG		0x40
 #define ADM1025_REG_STATUS1		0x41
 #define ADM1025_REG_STATUS2		0x42
@@ -92,7 +93,7 @@
  * The ADM1025 uses signed 8-bit values for temperatures.
  */
 
-static int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
+static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
 
 #define IN_FROM_REG(reg,scale)	(((reg) * (scale) + 96) / 192)
 #define IN_TO_REG(val,scale)	((val) <= 0 ? 0 : \
@@ -122,7 +123,6 @@
 	.driver = {
 		.name	= "adm1025",
 	},
-	.id		= I2C_DRIVERID_ADM1025,
 	.attach_adapter	= adm1025_attach_adapter,
 	.detach_client	= adm1025_detach_client,
 };
@@ -153,86 +153,96 @@
  * Sysfs stuff
  */
 
-#define show_in(offset) \
-static ssize_t show_in##offset(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct adm1025_data *data = adm1025_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
-		       in_scale[offset])); \
-} \
-static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct adm1025_data *data = adm1025_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
-		       in_scale[offset])); \
-} \
-static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct adm1025_data *data = adm1025_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
-		       in_scale[offset])); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);
-show_in(0);
-show_in(1);
-show_in(2);
-show_in(3);
-show_in(4);
-show_in(5);
+static ssize_t
+show_in(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[index],
+		       in_scale[index]));
+}
 
-#define show_temp(offset) \
-static ssize_t show_temp##offset(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct adm1025_data *data = adm1025_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct adm1025_data *data = adm1025_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct adm1025_data *data = adm1025_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
-}\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp##offset, NULL);
-show_temp(1);
-show_temp(2);
+static ssize_t
+show_in_min(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[index],
+		       in_scale[index]));
+}
+
+static ssize_t
+show_in_max(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[index],
+		       in_scale[index]));
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[index]));
+}
+
+static ssize_t
+show_temp_min(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[index]));
+}
+
+static ssize_t
+show_temp_max(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index]));
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1025_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->in_min[index] = IN_TO_REG(val, in_scale[index]);
+	i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(index),
+				  data->in_min[index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1025_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->in_max[index] = IN_TO_REG(val, in_scale[index]);
+	i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(index),
+				  data->in_max[index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
 
 #define set_in(offset) \
-static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct adm1025_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock); \
-	data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \
-	i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \
-				  data->in_min[offset]); \
-	mutex_unlock(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct adm1025_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock); \
-	data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \
-	i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \
-				  data->in_max[offset]); \
-	mutex_unlock(&data->update_lock); \
-	return count; \
-} \
-static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
-	show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
-	show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+	show_in, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
+	show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
+	show_in_max, set_in_max, offset)
 set_in(0);
 set_in(1);
 set_in(2);
@@ -240,65 +250,91 @@
 set_in(4);
 set_in(5);
 
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1025_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp_min[index] = TEMP_TO_REG(val);
+	i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(index),
+				  data->temp_min[index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1025_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp_max[index] = TEMP_TO_REG(val);
+	i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(index),
+				  data->temp_max[index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
 #define set_temp(offset) \
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct adm1025_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock); \
-	data->temp_min[offset-1] = TEMP_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \
-				  data->temp_min[offset-1]); \
-	mutex_unlock(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct adm1025_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock); \
-	data->temp_max[offset-1] = TEMP_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \
-				  data->temp_max[offset-1]); \
-	mutex_unlock(&data->update_lock); \
-	return count; \
-} \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_max, set_temp##offset##_max);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+	show_temp, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+	show_temp_min, set_temp_min, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+	show_temp_max, set_temp_max, offset - 1)
 set_temp(1);
 set_temp(2);
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t
+show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1025_data *data = adm1025_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t
+show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct adm1025_data *data = adm1025_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14);
+
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1025_data *data = adm1025_update_device(dev);
 	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t
+show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1025_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", data->vrm);
 }
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1025_data *data = i2c_get_clientdata(client);
+	struct adm1025_data *data = dev_get_drvdata(dev);
 	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
@@ -316,27 +352,35 @@
 }
 
 static struct attribute *adm1025_attributes[] = {
-	&dev_attr_in0_input.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in2_input.attr,
-	&dev_attr_in3_input.attr,
-	&dev_attr_in5_input.attr,
-	&dev_attr_in0_min.attr,
-	&dev_attr_in1_min.attr,
-	&dev_attr_in2_min.attr,
-	&dev_attr_in3_min.attr,
-	&dev_attr_in5_min.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in1_max.attr,
-	&dev_attr_in2_max.attr,
-	&dev_attr_in3_max.attr,
-	&dev_attr_in5_max.attr,
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp2_input.attr,
-	&dev_attr_temp1_min.attr,
-	&dev_attr_temp2_min.attr,
-	&dev_attr_temp1_max.attr,
-	&dev_attr_temp2_max.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
 	&dev_attr_alarms.attr,
 	&dev_attr_cpu0_vid.attr,
 	&dev_attr_vrm.attr,
@@ -347,15 +391,16 @@
 	.attrs = adm1025_attributes,
 };
 
-static struct attribute *adm1025_attributes_opt[] = {
-	&dev_attr_in4_input.attr,
-	&dev_attr_in4_min.attr,
-	&dev_attr_in4_max.attr,
+static struct attribute *adm1025_attributes_in4[] = {
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
 	NULL
 };
 
-static const struct attribute_group adm1025_group_opt = {
-	.attrs = adm1025_attributes_opt,
+static const struct attribute_group adm1025_group_in4 = {
+	.attrs = adm1025_attributes_in4,
 };
 
 /*
@@ -364,7 +409,7 @@
  */
 static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct adm1025_data *data;
 	int err = 0;
 	const char *name = "";
@@ -378,14 +423,11 @@
 		goto exit;
 	}
 
-	/* The common I2C client data is placed right before the
-	   ADM1025-specific data. */
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &adm1025_driver;
-	new_client->flags = 0;
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &adm1025_driver;
 
 	/*
 	 * Now we do the remaining detection. A negative kind means that
@@ -397,12 +439,12 @@
 	 * requested, so both the detection and the identification steps
 	 * are skipped.
 	 */
-	config = i2c_smbus_read_byte_data(new_client, ADM1025_REG_CONFIG);
+	config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
 	if (kind < 0) { /* detection */
 		if ((config & 0x80) != 0x00
-		 || (i2c_smbus_read_byte_data(new_client,
+		 || (i2c_smbus_read_byte_data(client,
 		     ADM1025_REG_STATUS1) & 0xC0) != 0x00
-		 || (i2c_smbus_read_byte_data(new_client,
+		 || (i2c_smbus_read_byte_data(client,
 		     ADM1025_REG_STATUS2) & 0xBC) != 0x00) {
 			dev_dbg(&adapter->dev,
 				"ADM1025 detection failed at 0x%02x.\n",
@@ -414,11 +456,9 @@
 	if (kind <= 0) { /* identification */
 		u8 man_id, chip_id;
 
-		man_id = i2c_smbus_read_byte_data(new_client,
-			 ADM1025_REG_MAN_ID);
-		chip_id = i2c_smbus_read_byte_data(new_client,
-			  ADM1025_REG_CHIP_ID);
-		
+		man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID);
+		chip_id = i2c_smbus_read_byte_data(client, ADM1025_REG_CHIP_ID);
+
 		if (man_id == 0x41) { /* Analog Devices */
 			if ((chip_id & 0xF0) == 0x20) { /* ADM1025/ADM1025A */
 				kind = adm1025;
@@ -446,33 +486,28 @@
 	}
 
 	/* We can fill in the remaining client fields */
-	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	data->valid = 0;
+	strlcpy(client->name, name, I2C_NAME_SIZE);
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
 	/* Initialize the ADM1025 chip */
-	adm1025_init_client(new_client);
+	adm1025_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1025_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group)))
 		goto exit_detach;
 
 	/* Pin 11 is either in4 (+12V) or VID4 */
 	if (!(config & 0x20)) {
-		if ((err = device_create_file(&new_client->dev,
-					&dev_attr_in4_input))
-		 || (err = device_create_file(&new_client->dev,
-					&dev_attr_in4_min))
-		 || (err = device_create_file(&new_client->dev,
-					&dev_attr_in4_max)))
+		if ((err = sysfs_create_group(&client->dev.kobj,
+					      &adm1025_group_in4)))
 			goto exit_remove;
 	}
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exit_remove;
@@ -481,10 +516,10 @@
 	return 0;
 
 exit_remove:
-	sysfs_remove_group(&new_client->dev.kobj, &adm1025_group);
-	sysfs_remove_group(&new_client->dev.kobj, &adm1025_group_opt);
+	sysfs_remove_group(&client->dev.kobj, &adm1025_group);
+	sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
 exit_detach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 exit_free:
 	kfree(data);
 exit:
@@ -540,7 +575,7 @@
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &adm1025_group);
-	sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt);
+	sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 3e63c14..8002f68 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -40,8 +40,8 @@
 /* Insmod parameters */
 I2C_CLIENT_INSMOD_1(adm1026);
 
-static int gpio_input[17]  = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
-				-1, -1, -1, -1, -1, -1, -1, -1 }; 
+static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1 };
 static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
 				-1, -1, -1, -1, -1, -1, -1, -1 };
 static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -49,46 +49,49 @@
 static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
 				-1, -1, -1, -1, -1, -1, -1, -1 };
 static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-module_param_array(gpio_input,int,NULL,0);
-MODULE_PARM_DESC(gpio_input,"List of GPIO pins (0-16) to program as inputs");
-module_param_array(gpio_output,int,NULL,0);
-MODULE_PARM_DESC(gpio_output,"List of GPIO pins (0-16) to program as "
+module_param_array(gpio_input, int, NULL, 0);
+MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
+module_param_array(gpio_output, int, NULL, 0);
+MODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as "
 	"outputs");
-module_param_array(gpio_inverted,int,NULL,0);
-MODULE_PARM_DESC(gpio_inverted,"List of GPIO pins (0-16) to program as "
+module_param_array(gpio_inverted, int, NULL, 0);
+MODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as "
 	"inverted");
-module_param_array(gpio_normal,int,NULL,0);
-MODULE_PARM_DESC(gpio_normal,"List of GPIO pins (0-16) to program as "
+module_param_array(gpio_normal, int, NULL, 0);
+MODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as "
 	"normal/non-inverted");
-module_param_array(gpio_fan,int,NULL,0);
-MODULE_PARM_DESC(gpio_fan,"List of GPIO pins (0-7) to program as fan tachs");
+module_param_array(gpio_fan, int, NULL, 0);
+MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
 
 /* Many ADM1026 constants specified below */
 
 /* The ADM1026 registers */
-#define ADM1026_REG_CONFIG1  0x00
-#define CFG1_MONITOR     0x01
-#define CFG1_INT_ENABLE  0x02
-#define CFG1_INT_CLEAR   0x04
-#define CFG1_AIN8_9      0x08
-#define CFG1_THERM_HOT   0x10
-#define CFG1_DAC_AFC     0x20
-#define CFG1_PWM_AFC     0x40
-#define CFG1_RESET       0x80
-#define ADM1026_REG_CONFIG2  0x01
+#define ADM1026_REG_CONFIG1	0x00
+#define CFG1_MONITOR		0x01
+#define CFG1_INT_ENABLE		0x02
+#define CFG1_INT_CLEAR		0x04
+#define CFG1_AIN8_9		0x08
+#define CFG1_THERM_HOT		0x10
+#define CFG1_DAC_AFC		0x20
+#define CFG1_PWM_AFC		0x40
+#define CFG1_RESET		0x80
+
+#define ADM1026_REG_CONFIG2	0x01
 /* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
-#define ADM1026_REG_CONFIG3  0x07
-#define CFG3_GPIO16_ENABLE  0x01
-#define CFG3_CI_CLEAR  0x02
-#define CFG3_VREF_250  0x04
-#define CFG3_GPIO16_DIR  0x40
-#define CFG3_GPIO16_POL  0x80
-#define ADM1026_REG_E2CONFIG  0x13
-#define E2CFG_READ  0x01
-#define E2CFG_WRITE  0x02
-#define E2CFG_ERASE  0x04
-#define E2CFG_ROM  0x08
-#define E2CFG_CLK_EXT  0x80
+
+#define ADM1026_REG_CONFIG3	0x07
+#define CFG3_GPIO16_ENABLE	0x01
+#define CFG3_CI_CLEAR		0x02
+#define CFG3_VREF_250		0x04
+#define CFG3_GPIO16_DIR		0x40
+#define CFG3_GPIO16_POL		0x80
+
+#define ADM1026_REG_E2CONFIG	0x13
+#define E2CFG_READ		0x01
+#define E2CFG_WRITE		0x02
+#define E2CFG_ERASE		0x04
+#define E2CFG_ROM		0x08
+#define E2CFG_CLK_EXT		0x80
 
 /* There are 10 general analog inputs and 7 dedicated inputs
  * They are:
@@ -129,48 +132,48 @@
 static u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
 static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
 
-#define ADM1026_REG_FAN(nr) (0x38 + (nr))
-#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr))
-#define ADM1026_REG_FAN_DIV_0_3 0x02
-#define ADM1026_REG_FAN_DIV_4_7 0x03
+#define ADM1026_REG_FAN(nr)		(0x38 + (nr))
+#define ADM1026_REG_FAN_MIN(nr)		(0x60 + (nr))
+#define ADM1026_REG_FAN_DIV_0_3		0x02
+#define ADM1026_REG_FAN_DIV_4_7		0x03
 
-#define ADM1026_REG_DAC  0x04
-#define ADM1026_REG_PWM  0x05
+#define ADM1026_REG_DAC			0x04
+#define ADM1026_REG_PWM			0x05
 
-#define ADM1026_REG_GPIO_CFG_0_3 0x08
-#define ADM1026_REG_GPIO_CFG_4_7 0x09
-#define ADM1026_REG_GPIO_CFG_8_11 0x0a
-#define ADM1026_REG_GPIO_CFG_12_15 0x0b
+#define ADM1026_REG_GPIO_CFG_0_3	0x08
+#define ADM1026_REG_GPIO_CFG_4_7	0x09
+#define ADM1026_REG_GPIO_CFG_8_11	0x0a
+#define ADM1026_REG_GPIO_CFG_12_15	0x0b
 /* CFG_16 in REG_CFG3 */
-#define ADM1026_REG_GPIO_STATUS_0_7 0x24
-#define ADM1026_REG_GPIO_STATUS_8_15 0x25
+#define ADM1026_REG_GPIO_STATUS_0_7	0x24
+#define ADM1026_REG_GPIO_STATUS_8_15	0x25
 /* STATUS_16 in REG_STATUS4 */
-#define ADM1026_REG_GPIO_MASK_0_7 0x1c
-#define ADM1026_REG_GPIO_MASK_8_15 0x1d
+#define ADM1026_REG_GPIO_MASK_0_7	0x1c
+#define ADM1026_REG_GPIO_MASK_8_15	0x1d
 /* MASK_16 in REG_MASK4 */
 
-#define ADM1026_REG_COMPANY 0x16
-#define ADM1026_REG_VERSTEP 0x17
+#define ADM1026_REG_COMPANY		0x16
+#define ADM1026_REG_VERSTEP		0x17
 /* These are the recognized values for the above regs */
-#define ADM1026_COMPANY_ANALOG_DEV 0x41
-#define ADM1026_VERSTEP_GENERIC 0x40
-#define ADM1026_VERSTEP_ADM1026 0x44
+#define ADM1026_COMPANY_ANALOG_DEV	0x41
+#define ADM1026_VERSTEP_GENERIC		0x40
+#define ADM1026_VERSTEP_ADM1026		0x44
 
-#define ADM1026_REG_MASK1 0x18
-#define ADM1026_REG_MASK2 0x19
-#define ADM1026_REG_MASK3 0x1a
-#define ADM1026_REG_MASK4 0x1b
+#define ADM1026_REG_MASK1		0x18
+#define ADM1026_REG_MASK2		0x19
+#define ADM1026_REG_MASK3		0x1a
+#define ADM1026_REG_MASK4		0x1b
 
-#define ADM1026_REG_STATUS1 0x20
-#define ADM1026_REG_STATUS2 0x21
-#define ADM1026_REG_STATUS3 0x22
-#define ADM1026_REG_STATUS4 0x23
+#define ADM1026_REG_STATUS1		0x20
+#define ADM1026_REG_STATUS2		0x21
+#define ADM1026_REG_STATUS3		0x22
+#define ADM1026_REG_STATUS4		0x23
 
 #define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
-#define ADM1026_FAN_CONTROL_TEMP_RANGE 20
-#define ADM1026_PWM_MAX 255
+#define ADM1026_FAN_CONTROL_TEMP_RANGE	20
+#define ADM1026_PWM_MAX			255
 
-/* Conversions. Rounding and limit checking is only done on the TO_REG 
+/* Conversions. Rounding and limit checking is only done on the TO_REG
  * variants. Note that you should be a bit careful with which arguments
  * these macros are called: arguments may be evaluated more than once.
  */
@@ -186,52 +189,49 @@
  * The values in this table are based on Table II, page 15 of the
  *    datasheet.
  */
-static int adm1026_scaling[] = {  /* .001 Volts */
-		2250, 2250, 2250, 2250, 2250, 2250, 
-		1875, 1875, 1875, 1875, 3000, 3330, 
+static int adm1026_scaling[] = { /* .001 Volts */
+		2250, 2250, 2250, 2250, 2250, 2250,
+		1875, 1875, 1875, 1875, 3000, 3330,
 		3330, 4995, 2250, 12000, 13875
 	};
 #define NEG12_OFFSET  16000
-#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
-#define INS_TO_REG(n,val)  (SENSORS_LIMIT(SCALE(val,adm1026_scaling[n],192),\
-	0,255))
-#define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n]))
+#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
+#define INS_TO_REG(n, val)  (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\
+	0, 255))
+#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
 
 /* FAN speed is measured using 22.5kHz clock and counts for 2 pulses
  *   and we assume a 2 pulse-per-rev fan tach signal
  *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
  */
-#define FAN_TO_REG(val,div)  ((val)<=0 ? 0xff : SENSORS_LIMIT(1350000/((val)*\
-	(div)),1,254)) 
-#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==0xff ? 0 : 1350000/((val)*\
-	(div)))
+#define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
+				SENSORS_LIMIT(1350000/((val)*(div)), 1, 254))
+#define FAN_FROM_REG(val, div) ((val) == 0 ? -1:(val) == 0xff ? 0 : \
+				1350000/((val)*(div)))
 #define DIV_FROM_REG(val) (1<<(val))
-#define DIV_TO_REG(val) ((val)>=8 ? 3 : (val)>=4 ? 2 : (val)>=2 ? 1 : 0)
+#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
 
 /* Temperature is reported in 1 degC increments */
 #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
-	-127,127))
+	-127, 127))
 #define TEMP_FROM_REG(val) ((val) * 1000)
 #define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
-	-127,127))
+	-127, 127))
 #define OFFSET_FROM_REG(val) ((val) * 1000)
 
-#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
+#define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255))
 #define PWM_FROM_REG(val) (val)
 
 #define PWM_MIN_TO_REG(val) ((val) & 0xf0)
 #define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
 
-/* Analog output is a voltage, and scaled to millivolts.  The datasheet 
- *   indicates that the DAC could be used to drive the fans, but in our 
+/* Analog output is a voltage, and scaled to millivolts.  The datasheet
+ *   indicates that the DAC could be used to drive the fans, but in our
  *   example board (Arima HDAMA) it isn't connected to the fans at all.
  */
-#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500),0,255)) 
+#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255))
 #define DAC_FROM_REG(val) (((val)*2500)/255)
 
-/* Typically used with systems using a v9.1 VRM spec ? */
-#define ADM1026_INIT_VRM  91
-
 /* Chip sampling rates
  *
  * Some sensors are not updated more frequently than once per second
@@ -243,8 +243,8 @@
  *    So, we keep the config data up to date in the cache
  *    when it is written and only sample it once every 5 *minutes*
  */
-#define ADM1026_DATA_INTERVAL  (1 * HZ)
-#define ADM1026_CONFIG_INTERVAL  (5 * 60 * HZ)
+#define ADM1026_DATA_INTERVAL		(1 * HZ)
+#define ADM1026_CONFIG_INTERVAL		(5 * 60 * HZ)
 
 /* We allow for multiple chips in a single system.
  *
@@ -261,37 +261,36 @@
 struct adm1026_data {
 	struct i2c_client client;
 	struct device *hwmon_dev;
-	enum chips type;
 
 	struct mutex update_lock;
 	int valid;		/* !=0 if following fields are valid */
 	unsigned long last_reading;	/* In jiffies */
 	unsigned long last_config;	/* In jiffies */
 
-	u8 in[17];              /* Register value */
-	u8 in_max[17];          /* Register value */
-	u8 in_min[17];          /* Register value */
-	s8 temp[3];             /* Register value */
-	s8 temp_min[3];         /* Register value */
-	s8 temp_max[3];         /* Register value */
-	s8 temp_tmin[3];        /* Register value */
-	s8 temp_crit[3];        /* Register value */
-	s8 temp_offset[3];      /* Register value */
-	u8 fan[8];              /* Register value */
-	u8 fan_min[8];          /* Register value */
-	u8 fan_div[8];          /* Decoded value */
-	struct pwm_data pwm1;   /* Pwm control values */
-	int vid;                /* Decoded value */
-	u8 vrm;                 /* VRM version */
+	u8 in[17];		/* Register value */
+	u8 in_max[17];		/* Register value */
+	u8 in_min[17];		/* Register value */
+	s8 temp[3];		/* Register value */
+	s8 temp_min[3];		/* Register value */
+	s8 temp_max[3];		/* Register value */
+	s8 temp_tmin[3];	/* Register value */
+	s8 temp_crit[3];	/* Register value */
+	s8 temp_offset[3];	/* Register value */
+	u8 fan[8];		/* Register value */
+	u8 fan_min[8];		/* Register value */
+	u8 fan_div[8];		/* Decoded value */
+	struct pwm_data pwm1;	/* Pwm control values */
+	int vid;		/* Decoded value */
+	u8 vrm;			/* VRM version */
 	u8 analog_out;		/* Register value (DAC) */
-	long alarms;            /* Register encoding, combined */
-	long alarm_mask;        /* Register encoding, combined */
-	long gpio;              /* Register encoding, combined */
-	long gpio_mask;         /* Register encoding, combined */
-	u8 gpio_config[17];     /* Decoded value */
-	u8 config1;             /* Register value */
-	u8 config2;             /* Register value */
-	u8 config3;             /* Register value */
+	long alarms;		/* Register encoding, combined */
+	long alarm_mask;	/* Register encoding, combined */
+	long gpio;		/* Register encoding, combined */
+	long gpio_mask;		/* Register encoding, combined */
+	u8 gpio_config[17];	/* Decoded value */
+	u8 config1;		/* Register value */
+	u8 config2;		/* Register value */
+	u8 config3;		/* Register value */
 };
 
 static int adm1026_attach_adapter(struct i2c_adapter *adapter);
@@ -301,7 +300,7 @@
 static int adm1026_read_value(struct i2c_client *client, u8 reg);
 static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
 static void adm1026_print_gpio(struct i2c_client *client);
-static void adm1026_fixup_gpio(struct i2c_client *client); 
+static void adm1026_fixup_gpio(struct i2c_client *client);
 static struct adm1026_data *adm1026_update_device(struct device *dev);
 static void adm1026_init_client(struct i2c_client *client);
 
@@ -311,7 +310,7 @@
 		.name	= "adm1026",
 	},
 	.attach_adapter = adm1026_attach_adapter,
-	.detach_client  = adm1026_detach_client,
+	.detach_client	= adm1026_detach_client,
 };
 
 static int adm1026_attach_adapter(struct i2c_adapter *adapter)
@@ -355,7 +354,7 @@
 	int value, i;
 	struct adm1026_data *data = i2c_get_clientdata(client);
 
-        dev_dbg(&client->dev, "Initializing device\n");
+	dev_dbg(&client->dev, "Initializing device\n");
 	/* Read chip config */
 	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
 	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
@@ -384,7 +383,6 @@
 			"and temp limits enabled.\n");
 	}
 
-	value = data->config3;
 	if (data->config3 & CFG3_GPIO16_ENABLE) {
 		dev_dbg(&client->dev, "GPIO16 enabled.  THERM "
 			"pin disabled.\n");
@@ -426,10 +424,10 @@
 	 *   configured, we don't want to mess with them.
 	 *   If they weren't, the default is 100% PWM, no
 	 *   control and will suffice until 'sensors -s'
-	 *   can be run by the user.  We DO set the default 
+	 *   can be run by the user.  We DO set the default
 	 *   value for pwm1.auto_pwm_min to its maximum
 	 *   so that enabling automatic pwm fan control
-	 *   without first setting a value for pwm1.auto_pwm_min 
+	 *   without first setting a value for pwm1.auto_pwm_min
 	 *   will not result in potentially dangerous fan speed decrease.
 	 */
 	data->pwm1.auto_pwm_min=255;
@@ -453,7 +451,7 @@
 static void adm1026_print_gpio(struct i2c_client *client)
 {
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int  i;
+	int i;
 
 	dev_dbg(&client->dev, "GPIO config is:");
 	for (i = 0;i <= 7;++i) {
@@ -477,7 +475,7 @@
 			data->gpio_config[16] & 0x02 ? "" : "!",
 			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
 	} else {
-		/* GPIO16 is THERM  */
+		/* GPIO16 is THERM */
 		dev_dbg(&client->dev, "\tTHERM\n");
 	}
 }
@@ -485,8 +483,8 @@
 static void adm1026_fixup_gpio(struct i2c_client *client)
 {
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int  i;
-	int  value;
+	int i;
+	int value;
 
 	/* Make the changes requested. */
 	/* We may need to unlock/stop monitoring or soft-reset the
@@ -516,14 +514,14 @@
 		}
 	}
 
-	/* Inverted  */
+	/* Inverted */
 	for (i = 0;i <= 16;++i) {
 		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) {
 			data->gpio_config[gpio_inverted[i]] &= ~ 0x02;
 		}
 	}
 
-	/* Normal overrides inverted  */
+	/* Normal overrides inverted */
 	for (i = 0;i <= 16;++i) {
 		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) {
 			data->gpio_config[gpio_normal[i]] |= 0x02;
@@ -569,7 +567,7 @@
 	if (!data->valid
 	    || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
 		/* Things that change quickly */
-		dev_dbg(&client->dev,"Reading sensor values\n");
+		dev_dbg(&client->dev, "Reading sensor values\n");
 		for (i = 0;i <= 16;++i) {
 			data->in[i] =
 			    adm1026_read_value(client, ADM1026_REG_IN[i]);
@@ -582,18 +580,18 @@
 
 		for (i = 0;i <= 2;++i) {
 			/* NOTE: temp[] is s8 and we assume 2's complement
-			 *   "conversion" in the assignment   */
+			 *   "conversion" in the assignment */
 			data->temp[i] =
 			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
 		}
 
-		data->pwm1.pwm = adm1026_read_value(client, 
+		data->pwm1.pwm = adm1026_read_value(client,
 			ADM1026_REG_PWM);
-		data->analog_out = adm1026_read_value(client, 
+		data->analog_out = adm1026_read_value(client,
 			ADM1026_REG_DAC);
 		/* GPIO16 is MSbit of alarms, move it to gpio */
 		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
-		gpio = alarms & 0x80 ? 0x0100 : 0;  /* GPIO16 */
+		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
 		alarms &= 0x7f;
 		alarms <<= 8;
 		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
@@ -604,24 +602,24 @@
 		data->alarms = alarms;
 
 		/* Read the GPIO values */
-		gpio |= adm1026_read_value(client, 
+		gpio |= adm1026_read_value(client,
 			ADM1026_REG_GPIO_STATUS_8_15);
 		gpio <<= 8;
-		gpio |= adm1026_read_value(client, 
+		gpio |= adm1026_read_value(client,
 			ADM1026_REG_GPIO_STATUS_0_7);
 		data->gpio = gpio;
 
 		data->last_reading = jiffies;
-	};  /* last_reading */
+	}; /* last_reading */
 
 	if (!data->valid ||
 	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
 		/* Things that don't change often */
 		dev_dbg(&client->dev, "Reading config values\n");
 		for (i = 0;i <= 16;++i) {
-			data->in_min[i] = adm1026_read_value(client, 
+			data->in_min[i] = adm1026_read_value(client,
 				ADM1026_REG_IN_MIN[i]);
-			data->in_max[i] = adm1026_read_value(client, 
+			data->in_max[i] = adm1026_read_value(client,
 				ADM1026_REG_IN_MAX[i]);
 		}
 
@@ -629,32 +627,32 @@
 			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
 			<< 8);
 		for (i = 0;i <= 7;++i) {
-			data->fan_min[i] = adm1026_read_value(client, 
+			data->fan_min[i] = adm1026_read_value(client,
 				ADM1026_REG_FAN_MIN(i));
 			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
 			value >>= 2;
 		}
 
 		for (i = 0; i <= 2; ++i) {
-			/* NOTE: temp_xxx[] are s8 and we assume 2's 
+			/* NOTE: temp_xxx[] are s8 and we assume 2's
 			 *    complement "conversion" in the assignment
 			 */
-			data->temp_min[i] = adm1026_read_value(client, 
+			data->temp_min[i] = adm1026_read_value(client,
 				ADM1026_REG_TEMP_MIN[i]);
-			data->temp_max[i] = adm1026_read_value(client, 
+			data->temp_max[i] = adm1026_read_value(client,
 				ADM1026_REG_TEMP_MAX[i]);
-			data->temp_tmin[i] = adm1026_read_value(client, 
+			data->temp_tmin[i] = adm1026_read_value(client,
 				ADM1026_REG_TEMP_TMIN[i]);
-			data->temp_crit[i] = adm1026_read_value(client, 
+			data->temp_crit[i] = adm1026_read_value(client,
 				ADM1026_REG_TEMP_THERM[i]);
-			data->temp_offset[i] = adm1026_read_value(client, 
+			data->temp_offset[i] = adm1026_read_value(client,
 				ADM1026_REG_TEMP_OFFSET[i]);
 		}
 
 		/* Read the STATUS/alarm masks */
-		alarms  = adm1026_read_value(client, ADM1026_REG_MASK4);
-		gpio    = alarms & 0x80 ? 0x0100 : 0;  /* GPIO16 */
-		alarms  = (alarms & 0x7f) << 8;
+		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
+		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
+		alarms = (alarms & 0x7f) << 8;
 		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
 		alarms <<= 8;
 		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
@@ -663,24 +661,24 @@
 		data->alarm_mask = alarms;
 
 		/* Read the GPIO values */
-		gpio |= adm1026_read_value(client, 
+		gpio |= adm1026_read_value(client,
 			ADM1026_REG_GPIO_MASK_8_15);
 		gpio <<= 8;
 		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
 		data->gpio_mask = gpio;
 
 		/* Read various values from CONFIG1 */
-		data->config1 = adm1026_read_value(client, 
+		data->config1 = adm1026_read_value(client,
 			ADM1026_REG_CONFIG1);
 		if (data->config1 & CFG1_PWM_AFC) {
 			data->pwm1.enable = 2;
-			data->pwm1.auto_pwm_min = 
+			data->pwm1.auto_pwm_min =
 				PWM_MIN_FROM_REG(data->pwm1.pwm);
 		}
 		/* Read the GPIO config */
-		data->config2 = adm1026_read_value(client, 
+		data->config2 = adm1026_read_value(client,
 			ADM1026_REG_CONFIG2);
-		data->config3 = adm1026_read_value(client, 
+		data->config3 = adm1026_read_value(client,
 			ADM1026_REG_CONFIG3);
 		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
 
@@ -695,7 +693,7 @@
 		}
 
 		data->last_config = jiffies;
-	};  /* last_config */
+	}; /* last_config */
 
 	dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n");
 	data->vid = (data->gpio >> 11) & 0x1f;
@@ -710,15 +708,15 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]));
+	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr]));
 }
 static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct adm1026_data *data = adm1026_update_device(dev); 
-	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]));
+	struct adm1026_data *data = adm1026_update_device(dev);
+	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr]));
 }
 static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -733,7 +731,7 @@
 	data->in_min[nr] = INS_TO_REG(nr, val);
 	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
 	mutex_unlock(&data->update_lock);
-	return count; 
+	return count;
 }
 static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -741,7 +739,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]));
+	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr]));
 }
 static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -788,13 +786,13 @@
 static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) -
+	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
 		NEG12_OFFSET);
 }
 static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct adm1026_data *data = adm1026_update_device(dev); 
-	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16])
+	struct adm1026_data *data = adm1026_update_device(dev);
+	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
 		- NEG12_OFFSET);
 }
 static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -807,12 +805,12 @@
 	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
 	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
 	mutex_unlock(&data->update_lock);
-	return count; 
+	return count;
 }
 static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16])
+	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
 			- NEG12_OFFSET);
 }
 static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -843,7 +841,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 		data->fan_div[nr]));
 }
 static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
@@ -852,7 +850,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
 		data->fan_div[nr]));
 }
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
@@ -872,10 +870,10 @@
 	return count;
 }
 
-#define fan_offset(offset)                                         		\
-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, 	\
-		offset - 1);							\
-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,           	\
+#define fan_offset(offset)						\
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL,	\
+		offset - 1);						\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
 		show_fan_min, set_fan_min, offset - 1);
 
 fan_offset(1);
@@ -892,8 +890,8 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int    new_min;
-	int    new_div = data->fan_div[fan];
+	int new_min;
+	int new_div = data->fan_div[fan];
 
 	/* 0 and 0xff are special.  Don't adjust them */
 	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) {
@@ -913,7 +911,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", data->fan_div[nr]);
+	return sprintf(buf, "%d\n", data->fan_div[nr]);
 }
 static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -922,10 +920,10 @@
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int    val,orig_div,new_div,shift;
+	int val, orig_div, new_div, shift;
 
 	val = simple_strtol(buf, NULL, 10);
-	new_div = DIV_TO_REG(val); 
+	new_div = DIV_TO_REG(val);
 	if (new_div == 0) {
 		return -EINVAL;
 	}
@@ -946,14 +944,14 @@
 	}
 
 	if (data->fan_div[nr] != orig_div) {
-		fixup_fan_min(dev,nr,orig_div);
+		fixup_fan_min(dev, nr, orig_div);
 	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-#define fan_offset_div(offset)                                          \
-static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,         \
+#define fan_offset_div(offset)						\
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
 		show_fan_div, set_fan_div, offset - 1);
 
 fan_offset_div(1);
@@ -972,7 +970,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
 }
 static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -980,7 +978,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
 }
 static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -1004,7 +1002,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
 }
 static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -1024,7 +1022,7 @@
 }
 
 #define temp_reg(offset)						\
-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, 	\
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,	\
 		NULL, offset - 1);					\
 static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
 		show_temp_min, set_temp_min, offset - 1);		\
@@ -1042,7 +1040,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
 }
 static ssize_t set_temp_offset(struct device *dev,
 		struct device_attribute *attr, const char *buf,
@@ -1076,7 +1074,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(
 		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
 }
 static ssize_t show_temp_auto_point2_temp(struct device *dev,
@@ -1085,7 +1083,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
 		ADM1026_FAN_CONTROL_TEMP_RANGE));
 }
 static ssize_t show_temp_auto_point1_temp(struct device *dev,
@@ -1094,7 +1092,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
 }
 static ssize_t set_temp_auto_point1_temp(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
@@ -1113,13 +1111,13 @@
 	return count;
 }
 
-#define temp_auto_point(offset)							\
-static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR,	\
-		show_temp_auto_point1_temp, set_temp_auto_point1_temp, 		\
-		offset - 1);							\
-static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,	\
-		show_temp_auto_point1_temp_hyst, NULL, offset - 1);		\
-static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,		\
+#define temp_auto_point(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp,		\
+		S_IRUGO | S_IWUSR, show_temp_auto_point1_temp,		\
+		set_temp_auto_point1_temp, offset - 1);			\
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\
+		show_temp_auto_point1_temp_hyst, NULL, offset - 1);	\
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,	\
 		show_temp_auto_point2_temp, NULL, offset - 1);
 
 temp_auto_point(1);
@@ -1130,7 +1128,7 @@
 		struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
+	return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
 }
 static ssize_t set_temp_crit_enable(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
@@ -1142,7 +1140,7 @@
 	if ((val == 1) || (val==0)) {
 		mutex_lock(&data->update_lock);
 		data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
-		adm1026_write_value(client, ADM1026_REG_CONFIG1, 
+		adm1026_write_value(client, ADM1026_REG_CONFIG1,
 			data->config1);
 		mutex_unlock(&data->update_lock);
 	}
@@ -1163,7 +1161,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
 }
 static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -1193,7 +1191,7 @@
 static ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out));
+	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
 }
 static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1209,26 +1207,25 @@
 	return count;
 }
 
-static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, 
+static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
 	set_analog_out_reg);
 
 static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = dev_get_drvdata(dev);
-	return sprintf(buf,"%d\n", data->vrm);
+	return sprintf(buf, "%d\n", data->vrm);
 }
 static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adm1026_data *data = i2c_get_clientdata(client);
+	struct adm1026_data *data = dev_get_drvdata(dev);
 
 	data->vrm = simple_strtol(buf, NULL, 10);
 	return count;
@@ -1239,15 +1236,52 @@
 static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) (data->alarms));
+	return sprintf(buf, "%ld\n", data->alarms);
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct adm1026_data *data = adm1026_update_device(dev);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1);
+}
+
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19);
+static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20);
+static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21);
+static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22);
+static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26);
+
 static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%ld\n", data->alarm_mask);
+	return sprintf(buf, "%ld\n", data->alarm_mask);
 }
 static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1283,7 +1317,7 @@
 static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%ld\n", data->gpio);
+	return sprintf(buf, "%ld\n", data->gpio);
 }
 static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1291,16 +1325,16 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
-	long   gpio;
+	long gpio;
 
 	mutex_lock(&data->update_lock);
 	data->gpio = val & 0x1ffff;
 	gpio = data->gpio;
-	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff);
+	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
 	gpio >>= 8;
-	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff);
+	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
 	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
-	adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff);
+	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1311,7 +1345,7 @@
 static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%ld\n", data->gpio_mask);
+	return sprintf(buf, "%ld\n", data->gpio_mask);
 }
 static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1319,16 +1353,16 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
-	long   mask;
+	long mask;
 
 	mutex_lock(&data->update_lock);
 	data->gpio_mask = val & 0x1ffff;
 	mask = data->gpio_mask;
-	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff);
+	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
 	mask >>= 8;
-	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff);
+	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
 	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
-	adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff);
+	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1338,7 +1372,7 @@
 static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm));
+	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
 }
 static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1359,7 +1393,7 @@
 static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min);
+	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
 }
 static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1369,10 +1403,10 @@
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
-	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255);
+	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255);
 	if (data->pwm1.enable == 2) { /* apply immediately */
 		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
-			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); 
+			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
 		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
 	}
 	mutex_unlock(&data->update_lock);
@@ -1380,12 +1414,12 @@
 }
 static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf,"%d\n", ADM1026_PWM_MAX);
+	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
 }
 static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
-	return sprintf(buf,"%d\n", data->pwm1.enable);
+	return sprintf(buf, "%d\n", data->pwm1.enable);
 }
 static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
@@ -1393,7 +1427,7 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
-	int     old_enable;
+	int old_enable;
 
 	if ((val >= 0) && (val < 3)) {
 		mutex_lock(&data->update_lock);
@@ -1403,15 +1437,15 @@
 				| ((val == 2) ? CFG1_PWM_AFC : 0);
 		adm1026_write_value(client, ADM1026_REG_CONFIG1,
 			data->config1);
-		if (val == 2) {  /* apply pwm1_auto_pwm_min to pwm1 */
+		if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
 			data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
-				PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); 
-			adm1026_write_value(client, ADM1026_REG_PWM, 
+				PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
+			adm1026_write_value(client, ADM1026_REG_PWM,
 				data->pwm1.pwm);
 		} else if (!((old_enable == 1) && (val == 1))) {
 			/* set pwm to safe value */
 			data->pwm1.pwm = 255;
-			adm1026_write_value(client, ADM1026_REG_PWM, 
+			adm1026_write_value(client, ADM1026_REG_PWM,
 				data->pwm1.pwm);
 		}
 		mutex_unlock(&data->update_lock);
@@ -1420,20 +1454,20 @@
 }
 
 /* enable PWM fan control */
-static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 
-static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 
-static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 
-static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 
+static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
+static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
+static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
+static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
 	set_pwm_enable);
-static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 
+static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
 	set_pwm_enable);
-static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 
+static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
 	set_pwm_enable);
-static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, 
+static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR,
 	show_auto_pwm_min, set_auto_pwm_min);
-static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, 
+static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR,
 	show_auto_pwm_min, set_auto_pwm_min);
-static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, 
+static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR,
 	show_auto_pwm_min, set_auto_pwm_min);
 
 static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
@@ -1444,105 +1478,115 @@
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_max.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in1_max.dev_attr.attr,
 	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
 	&sensor_dev_attr_in2_input.dev_attr.attr,
 	&sensor_dev_attr_in2_max.dev_attr.attr,
 	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
 	&sensor_dev_attr_in3_input.dev_attr.attr,
 	&sensor_dev_attr_in3_max.dev_attr.attr,
 	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
 	&sensor_dev_attr_in4_input.dev_attr.attr,
 	&sensor_dev_attr_in4_max.dev_attr.attr,
 	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
 	&sensor_dev_attr_in5_input.dev_attr.attr,
 	&sensor_dev_attr_in5_max.dev_attr.attr,
 	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
 	&sensor_dev_attr_in6_input.dev_attr.attr,
 	&sensor_dev_attr_in6_max.dev_attr.attr,
 	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in6_alarm.dev_attr.attr,
 	&sensor_dev_attr_in7_input.dev_attr.attr,
 	&sensor_dev_attr_in7_max.dev_attr.attr,
 	&sensor_dev_attr_in7_min.dev_attr.attr,
-	&sensor_dev_attr_in8_input.dev_attr.attr,
-	&sensor_dev_attr_in8_max.dev_attr.attr,
-	&sensor_dev_attr_in8_min.dev_attr.attr,
-	&sensor_dev_attr_in9_input.dev_attr.attr,
-	&sensor_dev_attr_in9_max.dev_attr.attr,
-	&sensor_dev_attr_in9_min.dev_attr.attr,
+	&sensor_dev_attr_in7_alarm.dev_attr.attr,
 	&sensor_dev_attr_in10_input.dev_attr.attr,
 	&sensor_dev_attr_in10_max.dev_attr.attr,
 	&sensor_dev_attr_in10_min.dev_attr.attr,
+	&sensor_dev_attr_in10_alarm.dev_attr.attr,
 	&sensor_dev_attr_in11_input.dev_attr.attr,
 	&sensor_dev_attr_in11_max.dev_attr.attr,
 	&sensor_dev_attr_in11_min.dev_attr.attr,
+	&sensor_dev_attr_in11_alarm.dev_attr.attr,
 	&sensor_dev_attr_in12_input.dev_attr.attr,
 	&sensor_dev_attr_in12_max.dev_attr.attr,
 	&sensor_dev_attr_in12_min.dev_attr.attr,
+	&sensor_dev_attr_in12_alarm.dev_attr.attr,
 	&sensor_dev_attr_in13_input.dev_attr.attr,
 	&sensor_dev_attr_in13_max.dev_attr.attr,
 	&sensor_dev_attr_in13_min.dev_attr.attr,
+	&sensor_dev_attr_in13_alarm.dev_attr.attr,
 	&sensor_dev_attr_in14_input.dev_attr.attr,
 	&sensor_dev_attr_in14_max.dev_attr.attr,
 	&sensor_dev_attr_in14_min.dev_attr.attr,
+	&sensor_dev_attr_in14_alarm.dev_attr.attr,
 	&sensor_dev_attr_in15_input.dev_attr.attr,
 	&sensor_dev_attr_in15_max.dev_attr.attr,
 	&sensor_dev_attr_in15_min.dev_attr.attr,
+	&sensor_dev_attr_in15_alarm.dev_attr.attr,
 	&sensor_dev_attr_in16_input.dev_attr.attr,
 	&sensor_dev_attr_in16_max.dev_attr.attr,
 	&sensor_dev_attr_in16_min.dev_attr.attr,
+	&sensor_dev_attr_in16_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan1_input.dev_attr.attr,
 	&sensor_dev_attr_fan1_div.dev_attr.attr,
 	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan2_input.dev_attr.attr,
 	&sensor_dev_attr_fan2_div.dev_attr.attr,
 	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan3_input.dev_attr.attr,
 	&sensor_dev_attr_fan3_div.dev_attr.attr,
 	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan4_input.dev_attr.attr,
 	&sensor_dev_attr_fan4_div.dev_attr.attr,
 	&sensor_dev_attr_fan4_min.dev_attr.attr,
+	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan5_input.dev_attr.attr,
 	&sensor_dev_attr_fan5_div.dev_attr.attr,
 	&sensor_dev_attr_fan5_min.dev_attr.attr,
+	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan6_input.dev_attr.attr,
 	&sensor_dev_attr_fan6_div.dev_attr.attr,
 	&sensor_dev_attr_fan6_min.dev_attr.attr,
+	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan7_input.dev_attr.attr,
 	&sensor_dev_attr_fan7_div.dev_attr.attr,
 	&sensor_dev_attr_fan7_min.dev_attr.attr,
+	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan8_input.dev_attr.attr,
 	&sensor_dev_attr_fan8_div.dev_attr.attr,
 	&sensor_dev_attr_fan8_min.dev_attr.attr,
+	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp2_input.dev_attr.attr,
 	&sensor_dev_attr_temp2_max.dev_attr.attr,
 	&sensor_dev_attr_temp2_min.dev_attr.attr,
-	&sensor_dev_attr_temp3_input.dev_attr.attr,
-	&sensor_dev_attr_temp3_max.dev_attr.attr,
-	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
-	&sensor_dev_attr_temp3_offset.dev_attr.attr,
 	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
 	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
 	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
 	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
-	&sensor_dev_attr_temp3_crit.dev_attr.attr,
 	&dev_attr_temp1_crit_enable.attr,
 	&dev_attr_temp2_crit_enable.attr,
-	&dev_attr_temp3_crit_enable.attr,
 	&dev_attr_cpu0_vid.attr,
 	&dev_attr_vrm.attr,
 	&dev_attr_alarms.attr,
@@ -1557,10 +1601,8 @@
 	&dev_attr_pwm3_enable.attr,
 	&dev_attr_temp1_auto_point1_pwm.attr,
 	&dev_attr_temp2_auto_point1_pwm.attr,
-	&dev_attr_temp3_auto_point1_pwm.attr,
 	&dev_attr_temp1_auto_point2_pwm.attr,
 	&dev_attr_temp2_auto_point2_pwm.attr,
-	&dev_attr_temp3_auto_point2_pwm.attr,
 	&dev_attr_analog_out.attr,
 	NULL
 };
@@ -1569,11 +1611,45 @@
 	.attrs = adm1026_attributes,
 };
 
+static struct attribute *adm1026_attributes_temp3[] = {
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&dev_attr_temp3_crit_enable.attr,
+	&dev_attr_temp3_auto_point1_pwm.attr,
+	&dev_attr_temp3_auto_point2_pwm.attr,
+};
+
+static const struct attribute_group adm1026_group_temp3 = {
+	.attrs = adm1026_attributes_temp3,
+};
+
+static struct attribute *adm1026_attributes_in8_9[] = {
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in8_max.dev_attr.attr,
+	&sensor_dev_attr_in8_min.dev_attr.attr,
+	&sensor_dev_attr_in8_alarm.dev_attr.attr,
+	&sensor_dev_attr_in9_input.dev_attr.attr,
+	&sensor_dev_attr_in9_max.dev_attr.attr,
+	&sensor_dev_attr_in9_min.dev_attr.attr,
+	&sensor_dev_attr_in9_alarm.dev_attr.attr,
+};
+
+static const struct attribute_group adm1026_group_in8_9 = {
+	.attrs = adm1026_attributes_in8_9,
+};
+
 static int adm1026_detect(struct i2c_adapter *adapter, int address,
 			  int kind)
 {
 	int company, verstep;
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct adm1026_data *data;
 	int err = 0;
 	const char *type_name = "";
@@ -1592,26 +1668,25 @@
 		goto exit;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &adm1026_driver;
-	new_client->flags = 0;
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &adm1026_driver;
 
 	/* Now, we do the remaining detection. */
 
-	company = adm1026_read_value(new_client, ADM1026_REG_COMPANY);
-	verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP);
+	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
+	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
 
-	dev_dbg(&new_client->dev, "Detecting device at %d,0x%02x with"
+	dev_dbg(&client->dev, "Detecting device at %d,0x%02x with"
 		" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
-		i2c_adapter_id(new_client->adapter), new_client->addr,
+		i2c_adapter_id(client->adapter), client->addr,
 		company, verstep);
 
 	/* If auto-detecting, Determine the chip type. */
 	if (kind <= 0) {
-		dev_dbg(&new_client->dev, "Autodetecting device at %d,0x%02x "
+		dev_dbg(&client->dev, "Autodetecting device at %d,0x%02x "
 			"...\n", i2c_adapter_id(adapter), address);
 		if (company == ADM1026_COMPANY_ANALOG_DEV
 		    && verstep == ADM1026_VERSTEP_ADM1026) {
@@ -1627,16 +1702,15 @@
 				verstep);
 			kind = any_chip;
 		} else {
-			dev_dbg(&new_client->dev, ": Autodetection "
+			dev_dbg(&client->dev, ": Autodetection "
 				"failed\n");
 			/* Not an ADM1026 ... */
-			if (kind == 0)  { /* User used force=x,y */
+			if (kind == 0) { /* User used force=x,y */
 				dev_err(&adapter->dev, "Generic ADM1026 not "
 					"found at %d,0x%02x.  Try "
 					"force_adm1026.\n",
 					i2c_adapter_id(adapter), address);
 			}
-			err = 0;
 			goto exitfree;
 		}
 	}
@@ -1655,28 +1729,34 @@
 		err = -EFAULT;
 		goto exitfree;
 	}
-	strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
+	strlcpy(client->name, type_name, I2C_NAME_SIZE);
 
 	/* Fill in the remaining client fields */
-	data->type = kind;
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto exitfree;
 
 	/* Set the VRM version */
 	data->vrm = vid_which_vrm();
 
 	/* Initialize the ADM1026 chip */
-	adm1026_init_client(new_client);
+	adm1026_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
 		goto exitdetach;
+	if (data->config1 & CFG1_AIN8_9)
+		err = sysfs_create_group(&client->dev.kobj,
+					 &adm1026_group_in8_9);
+	else
+		err = sysfs_create_group(&client->dev.kobj,
+					 &adm1026_group_temp3);
+	if (err)
+		goto exitremove;
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exitremove;
@@ -1686,9 +1766,13 @@
 
 	/* Error out and cleanup code */
 exitremove:
-	sysfs_remove_group(&new_client->dev.kobj, &adm1026_group);
+	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
+	if (data->config1 & CFG1_AIN8_9)
+		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
+	else
+		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
 exitdetach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 exitfree:
 	kfree(data);
 exit:
@@ -1700,6 +1784,10 @@
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
+	if (data->config1 & CFG1_AIN8_9)
+		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
+	else
+		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
 	i2c_detach_client(client);
 	kfree(data);
 	return 0;
@@ -1710,14 +1798,14 @@
 	return i2c_add_driver(&adm1026_driver);
 }
 
-static void  __exit sm_adm1026_exit(void)
+static void __exit sm_adm1026_exit(void)
 {
 	i2c_del_driver(&adm1026_driver);
 }
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
-              "Justin Thiessen <jthiessen@penguincomputing.com>");
+	      "Justin Thiessen <jthiessen@penguincomputing.com>");
 MODULE_DESCRIPTION("ADM1026 driver");
 
 module_init(sm_adm1026_init);
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 37cfc10..5aaad36 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -5,7 +5,7 @@
   Supports adm1030 / adm1031
   Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org>
   Reworked by Jean Delvare <khali@linux-fr.org>
-  
+
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
@@ -27,27 +27,28 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 
 /* Following macros takes channel parameter starting from 0 to 2 */
 #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
-#define ADM1031_REG_FAN_DIV(nr)		(0x20  + (nr))
+#define ADM1031_REG_FAN_DIV(nr)		(0x20 + (nr))
 #define ADM1031_REG_PWM			(0x22)
 #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
 
-#define ADM1031_REG_TEMP_MAX(nr)	(0x14  + 4*(nr))
-#define ADM1031_REG_TEMP_MIN(nr)	(0x15  + 4*(nr))
-#define ADM1031_REG_TEMP_CRIT(nr)	(0x16  + 4*(nr))
+#define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
+#define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
+#define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
 
-#define ADM1031_REG_TEMP(nr)		(0xa + (nr))
+#define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
 #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
 
 #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
 
-#define ADM1031_REG_CONF1		0x0
-#define ADM1031_REG_CONF2		0x1
-#define ADM1031_REG_EXT_TEMP		0x6
+#define ADM1031_REG_CONF1		0x00
+#define ADM1031_REG_CONF2		0x01
+#define ADM1031_REG_EXT_TEMP		0x06
 
 #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
 #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
@@ -78,7 +79,7 @@
 	/* The chan_select_table contains the possible configurations for
 	 * auto fan control.
 	 */
-	auto_chan_table_t *chan_select_table;
+	const auto_chan_table_t *chan_select_table;
 	u16 alarm;
 	u8 conf1;
 	u8 conf2;
@@ -181,25 +182,25 @@
 #define GET_FAN_AUTO_BITFIELD(data, idx)	\
 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
 
-/* The tables below contains the possible values for the auto fan 
+/* The tables below contains the possible values for the auto fan
  * control bitfields. the index in the table is the register value.
  * MSb is the auto fan control enable bit, so the four first entries
  * in the table disables auto fan control when both bitfields are zero.
  */
-static auto_chan_table_t auto_channel_select_table_adm1031 = {
-	{0, 0}, {0, 0}, {0, 0}, {0, 0},
-	{2 /*0b010 */ , 4 /*0b100 */ },
-	{2 /*0b010 */ , 2 /*0b010 */ },
-	{4 /*0b100 */ , 4 /*0b100 */ },
-	{7 /*0b111 */ , 7 /*0b111 */ },
+static const auto_chan_table_t auto_channel_select_table_adm1031 = {
+	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
+	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
+	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
+	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
+	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
 };
 
-static auto_chan_table_t auto_channel_select_table_adm1030 = {
-	{0, 0}, {0, 0}, {0, 0}, {0, 0},
-	{2 /*0b10 */		, 0},
-	{0xff /*invalid */	, 0},
-	{0xff /*invalid */	, 0},
-	{3 /*0b11 */		, 0},
+static const auto_chan_table_t auto_channel_select_table_adm1030 = {
+	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
+	{ 2 /* 0b10 */		, 0 },
+	{ 0xff /* invalid */	, 0 },
+	{ 0xff /* invalid */	, 0 },
+	{ 3 /* 0b11 */		, 0 },
 };
 
 /* That function checks if a bitfield is valid and returns the other bitfield
@@ -228,8 +229,8 @@
 			break;
 		} else if (val == (*data->chan_select_table)[i][chan] &&
 			   first_match == -1) {
-			/* Save the first match in case of an exact match has not been
-			 * found 
+			/* Save the first match in case of an exact match has
+			 * not been found
 			 */
 			first_match = i;
 		}
@@ -245,17 +246,21 @@
 	return 0;
 }
 
-static ssize_t show_fan_auto_channel(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_auto_channel(struct device *dev,
+				     struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
 }
 
 static ssize_t
-set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr)
+set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val = simple_strtol(buf, NULL, 10);
 	u8 reg;
 	int ret;
@@ -264,16 +269,17 @@
 	old_fan_mode = data->conf1;
 
 	mutex_lock(&data->update_lock);
-	
+
 	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
 		mutex_unlock(&data->update_lock);
 		return ret;
 	}
-	if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ 
+	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
+	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
-			/* Switch to Auto Fan Mode 
-			 * Save PWM registers 
+			/* Switch to Auto Fan Mode
+			 * Save PWM registers
 			 * Set PWM registers to 33% Both */
 			data->old_pwm[0] = data->pwm[0];
 			data->old_pwm[1] = data->pwm[1];
@@ -283,7 +289,7 @@
 			data->pwm[0] = data->old_pwm[0];
 			data->pwm[1] = data->old_pwm[1];
 			/* Restore PWM registers */
-			adm1031_write_value(client, ADM1031_REG_PWM, 
+			adm1031_write_value(client, ADM1031_REG_PWM,
 					    data->pwm[0] | (data->pwm[1] << 4));
 		}
 	}
@@ -293,41 +299,35 @@
 	return count;
 }
 
-#define fan_auto_channel_offset(offset)						\
-static ssize_t show_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
-{										\
-	return show_fan_auto_channel(dev, buf, offset - 1);			\
-}										\
-static ssize_t set_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr,		\
-	const char *buf, size_t count)						\
-{										\
-	return set_fan_auto_channel(dev, buf, count, offset - 1);		\
-}										\
-static DEVICE_ATTR(auto_fan##offset##_channel, S_IRUGO | S_IWUSR,		\
-		   show_fan_auto_channel_##offset,				\
-		   set_fan_auto_channel_##offset)
-
-fan_auto_channel_offset(1);
-fan_auto_channel_offset(2);
+static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR,
+		show_fan_auto_channel, set_fan_auto_channel, 0);
+static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR,
+		show_fan_auto_channel, set_fan_auto_channel, 1);
 
 /* Auto Temps */
-static ssize_t show_auto_temp_off(struct device *dev, char *buf, int nr)
+static ssize_t show_auto_temp_off(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
-	return sprintf(buf, "%d\n", 
+	return sprintf(buf, "%d\n",
 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
 }
-static ssize_t show_auto_temp_min(struct device *dev, char *buf, int nr)
+static ssize_t show_auto_temp_min(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n",
 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
 }
 static ssize_t
-set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr)
+set_auto_temp_min(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -337,17 +337,21 @@
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr)
+static ssize_t show_auto_temp_max(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n",
 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
 }
 static ssize_t
-set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr)
+set_auto_temp_max(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -358,56 +362,37 @@
 	return count;
 }
 
-#define auto_temp_reg(offset)							\
-static ssize_t show_auto_temp_##offset##_off (struct device *dev, struct device_attribute *attr, char *buf)	\
-{										\
-	return show_auto_temp_off(dev, buf, offset - 1);			\
-}										\
-static ssize_t show_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
-{										\
-	return show_auto_temp_min(dev, buf, offset - 1);			\
-}										\
-static ssize_t show_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
-{										\
-	return show_auto_temp_max(dev, buf, offset - 1);			\
-}										\
-static ssize_t set_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr,		\
-					     const char *buf, size_t count)	\
-{										\
-	return set_auto_temp_min(dev, buf, count, offset - 1);		\
-}										\
-static ssize_t set_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr,		\
-					     const char *buf, size_t count)	\
-{										\
-	return set_auto_temp_max(dev, buf, count, offset - 1);		\
-}										\
-static DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,				\
-		   show_auto_temp_##offset##_off, NULL);			\
-static DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,			\
-		   show_auto_temp_##offset##_min, set_auto_temp_##offset##_min);\
-static DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,			\
-		   show_auto_temp_##offset##_max, set_auto_temp_##offset##_max)
+#define auto_temp_reg(offset)						\
+static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,		\
+		show_auto_temp_off, NULL, offset - 1);			\
+static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_auto_temp_min, set_auto_temp_min, offset - 1);	\
+static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_auto_temp_max, set_auto_temp_max, offset - 1)
 
 auto_temp_reg(1);
 auto_temp_reg(2);
 auto_temp_reg(3);
 
 /* pwm */
-static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm(struct device *dev,
+			struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
 }
-static ssize_t
-set_pwm(struct device *dev, const char *buf, size_t count, int nr)
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val = simple_strtol(buf, NULL, 10);
 	int reg;
 
 	mutex_lock(&data->update_lock);
-	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && 
+	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
 	    (((val>>4) & 0xf) != 5)) {
 		/* In automatic mode, the only PWM accepted is 33% */
 		mutex_unlock(&data->update_lock);
@@ -422,21 +407,12 @@
 	return count;
 }
 
-#define pwm_reg(offset)							\
-static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_pwm(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr,			\
-				 const char *buf, size_t count)		\
-{									\
-	return set_pwm(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,			\
-		   show_pwm_##offset, set_pwm_##offset)
-
-pwm_reg(1);
-pwm_reg(2);
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR,
+		show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR,
+		show_pwm, set_pwm, 1);
 
 /* Fans */
 
@@ -471,7 +447,7 @@
 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
 			    || data->temp[1] >=
 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
-			    || (data->chip_type == adm1031 
+			    || (data->chip_type == adm1031
 				&& data->temp[2] >=
 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
 			break;
@@ -483,8 +459,10 @@
 }
 
 
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev,
+			struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	int value;
 
@@ -493,28 +471,33 @@
 	return sprintf(buf, "%d\n", value);
 }
 
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
 }
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n",
 		       FAN_FROM_REG(data->fan_min[nr],
 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
 }
-static ssize_t
-set_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	if (val) {
-		data->fan_min[nr] = 
+		data->fan_min[nr] =
 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
 	} else {
 		data->fan_min[nr] = 0xff;
@@ -523,11 +506,12 @@
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t
-set_fan_div(struct device *dev, const char *buf, size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val = simple_strtol(buf, NULL, 10);
 	u8 tmp;
 	int old_div;
@@ -535,68 +519,53 @@
 
 	tmp = val == 8 ? 0xc0 :
 	      val == 4 ? 0x80 :
-	      val == 2 ? 0x40 :	
-	      val == 1 ? 0x00 :  
+	      val == 2 ? 0x40 :
+	      val == 1 ? 0x00 :
 	      0xff;
 	if (tmp == 0xff)
 		return -EINVAL;
-	
-	mutex_lock(&data->update_lock);
-	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
-	data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]);
-	new_min = data->fan_min[nr] * old_div / 
-		FAN_DIV_FROM_REG(data->fan_div[nr]);
-	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
-	data->fan[nr] = data->fan[nr] * old_div / 
-		FAN_DIV_FROM_REG(data->fan_div[nr]);
 
-	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), 
+	mutex_lock(&data->update_lock);
+	/* Get fresh readings */
+	data->fan_div[nr] = adm1031_read_value(client,
+					       ADM1031_REG_FAN_DIV(nr));
+	data->fan_min[nr] = adm1031_read_value(client,
+					       ADM1031_REG_FAN_MIN(nr));
+
+	/* Write the new clock divider and fan min */
+	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
+	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
+	new_min = data->fan_min[nr] * old_div / val;
+	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
+
+	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
 			    data->fan_div[nr]);
-	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), 
+	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
 			    data->fan_min[nr]);
+
+	/* Invalidate the cache: fan speed is no longer valid */
+	data->valid = 0;
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
 #define fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan_min(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan_div(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,		\
-	const char *buf, size_t count)					\
-{									\
-	return set_fan_min(dev, buf, count, offset - 1);		\
-}									\
-static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr,		\
-	const char *buf, size_t count)					\
-{									\
-	return set_fan_div(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset,	\
-		   NULL);						\
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
-		   show_fan_##offset##_min, set_fan_##offset##_min);	\
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
-		   show_fan_##offset##_div, set_fan_##offset##_div);	\
-static DEVICE_ATTR(auto_fan##offset##_min_pwm, S_IRUGO | S_IWUSR,	\
-		   show_pwm_##offset, set_pwm_##offset)
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
+		show_fan, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
+		show_fan_min, set_fan_min, offset - 1);			\
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
+		show_fan_div, set_fan_div, offset - 1)
 
 fan_offset(1);
 fan_offset(2);
 
 
 /* Temps */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	int ext;
 	ext = nr == 0 ?
@@ -604,26 +573,33 @@
 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
 }
-static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_min(struct device *dev,
+			     struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
 }
-static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
 }
-static ssize_t show_temp_crit(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_crit(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
 }
-static ssize_t
-set_temp_min(struct device *dev, const char *buf, size_t count, int nr)
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val;
 
 	val = simple_strtol(buf, NULL, 10);
@@ -635,11 +611,12 @@
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t
-set_temp_max(struct device *dev, const char *buf, size_t count, int nr)
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val;
 
 	val = simple_strtol(buf, NULL, 10);
@@ -651,11 +628,12 @@
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t
-set_temp_crit(struct device *dev, const char *buf, size_t count, int nr)
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1031_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int val;
 
 	val = simple_strtol(buf, NULL, 10);
@@ -668,46 +646,15 @@
 	return count;
 }
 
-#define temp_reg(offset)							\
-static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
-{										\
-	return show_temp(dev, buf, offset - 1);				\
-}										\
-static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)		\
-{										\
-	return show_temp_min(dev, buf, offset - 1);				\
-}										\
-static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)		\
-{										\
-	return show_temp_max(dev, buf, offset - 1);				\
-}										\
-static ssize_t show_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, char *buf)	\
-{										\
-	return show_temp_crit(dev, buf, offset - 1);			\
-}										\
-static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr,			\
-					const char *buf, size_t count)		\
-{										\
-	return set_temp_min(dev, buf, count, offset - 1);			\
-}										\
-static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr,			\
-					const char *buf, size_t count)		\
-{										\
-	return set_temp_max(dev, buf, count, offset - 1);			\
-}										\
-static ssize_t set_temp_##offset##_crit (struct device *dev, struct device_attribute *attr,			\
-					 const char *buf, size_t count)		\
-{										\
-	return set_temp_crit(dev, buf, count, offset - 1);			\
-}										\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset,		\
-		   NULL);							\
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,			\
-		   show_temp_##offset##_min, set_temp_##offset##_min);		\
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,			\
-		   show_temp_##offset##_max, set_temp_##offset##_max);		\
-static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,			\
-		   show_temp_##offset##_crit, set_temp_##offset##_crit)
+#define temp_reg(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
+		show_temp, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_temp_min, set_temp_min, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_temp_max, set_temp_max, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
+		show_temp_crit, set_temp_crit, offset - 1)
 
 temp_reg(1);
 temp_reg(2);
@@ -722,6 +669,29 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_alarm(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct adm1031_data *data = adm1031_update_device(dev);
+	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
+}
+
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
 
 static int adm1031_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -731,29 +701,38 @@
 }
 
 static struct attribute *adm1031_attributes[] = {
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan1_div.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_pwm1.attr,
-	&dev_attr_auto_fan1_channel.attr,
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp1_min.attr,
-	&dev_attr_temp1_max.attr,
-	&dev_attr_temp1_crit.attr,
-	&dev_attr_temp2_input.attr,
-	&dev_attr_temp2_min.attr,
-	&dev_attr_temp2_max.attr,
-	&dev_attr_temp2_crit.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
 
-	&dev_attr_auto_temp1_off.attr,
-	&dev_attr_auto_temp1_min.attr,
-	&dev_attr_auto_temp1_max.attr,
+	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
+	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
 
-	&dev_attr_auto_temp2_off.attr,
-	&dev_attr_auto_temp2_min.attr,
-	&dev_attr_auto_temp2_max.attr,
+	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
+	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
 
-	&dev_attr_auto_fan1_min_pwm.attr,
+	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
 
@@ -765,19 +744,25 @@
 };
 
 static struct attribute *adm1031_attributes_opt[] = {
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan2_div.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_pwm2.attr,
-	&dev_attr_auto_fan2_channel.attr,
-	&dev_attr_temp3_input.attr,
-	&dev_attr_temp3_min.attr,
-	&dev_attr_temp3_max.attr,
-	&dev_attr_temp3_crit.attr,
-	&dev_attr_auto_temp3_off.attr,
-	&dev_attr_auto_temp3_min.attr,
-	&dev_attr_auto_temp3_max.attr,
-	&dev_attr_auto_fan2_min_pwm.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_fault.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
+	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
 	NULL
 };
 
@@ -788,7 +773,7 @@
 /* This function is called by i2c_probe */
 static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct adm1031_data *data;
 	int err = 0;
 	const char *name = "";
@@ -801,17 +786,16 @@
 		goto exit;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &adm1031_driver;
-	new_client->flags = 0;
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &adm1031_driver;
 
 	if (kind < 0) {
 		int id, co;
-		id = i2c_smbus_read_byte_data(new_client, 0x3d);
-		co = i2c_smbus_read_byte_data(new_client, 0x3e);
+		id = i2c_smbus_read_byte_data(client, 0x3d);
+		co = i2c_smbus_read_byte_data(client, 0x3e);
 
 		if (!((id == 0x31 || id == 0x30) && co == 0x41))
 			goto exit_free;
@@ -832,28 +816,27 @@
 	}
 	data->chip_type = kind;
 
-	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	data->valid = 0;
+	strlcpy(client->name, name, I2C_NAME_SIZE);
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
 	/* Initialize the ADM1031 chip */
-	adm1031_init_client(new_client);
+	adm1031_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1031_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
 		goto exit_detach;
 
 	if (kind == adm1031) {
-		if ((err = sysfs_create_group(&new_client->dev.kobj,
+		if ((err = sysfs_create_group(&client->dev.kobj,
 						&adm1031_group_opt)))
 			goto exit_remove;
 	}
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exit_remove;
@@ -862,10 +845,10 @@
 	return 0;
 
 exit_remove:
-	sysfs_remove_group(&new_client->dev.kobj, &adm1031_group);
-	sysfs_remove_group(&new_client->dev.kobj, &adm1031_group_opt);
+	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
+	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
 exit_detach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 exit_free:
 	kfree(data);
 exit:
@@ -897,7 +880,7 @@
 	if (data->chip_type == adm1031) {
 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
 			ADM1031_CONF2_TACH2_ENABLE);
-	} 
+	}
 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
 	if ((read_val | mask) != read_val) {
@@ -976,7 +959,7 @@
 		if (data->chip_type == adm1030) {
 			data->alarm &= 0xc0ff;
 		}
-		
+
 		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
 			data->fan_div[chan] =
 			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
@@ -985,7 +968,7 @@
 			data->fan[chan] =
 			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
 			data->pwm[chan] =
-			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >> 
+			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
 				   (4*chan));
 		}
 		data->last_updated = jiffies;
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index c17d0b6..7671d2b 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -141,7 +141,6 @@
 	.driver = {
 		.name	= "adm9240",
 	},
-	.id		= I2C_DRIVERID_ADM9240,
 	.attach_adapter	= adm9240_attach_adapter,
 	.detach_client	= adm9240_detach_client,
 };
@@ -415,6 +414,23 @@
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_alarm(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+
 /* vid */
 static ssize_t show_vid(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -469,30 +485,39 @@
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in1_min.dev_attr.attr,
 	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
 	&sensor_dev_attr_in2_input.dev_attr.attr,
 	&sensor_dev_attr_in2_min.dev_attr.attr,
 	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
 	&sensor_dev_attr_in3_input.dev_attr.attr,
 	&sensor_dev_attr_in3_min.dev_attr.attr,
 	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
 	&sensor_dev_attr_in4_input.dev_attr.attr,
 	&sensor_dev_attr_in4_min.dev_attr.attr,
 	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
 	&sensor_dev_attr_in5_input.dev_attr.attr,
 	&sensor_dev_attr_in5_min.dev_attr.attr,
 	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
 	&dev_attr_temp1_input.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan1_input.dev_attr.attr,
 	&sensor_dev_attr_fan1_div.dev_attr.attr,
 	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan2_input.dev_attr.attr,
 	&sensor_dev_attr_fan2_div.dev_attr.attr,
 	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
 	&dev_attr_alarms.attr,
 	&dev_attr_aout_output.attr,
 	&dev_attr_chassis_clear.attr,
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
new file mode 100644
index 0000000..6b8a73e
--- /dev/null
+++ b/drivers/hwmon/ads7828.c
@@ -0,0 +1,297 @@
+/*
+	ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC
+	(C) 2007 EADS Astrium
+
+	This driver is based on the lm75 and other lm_sensors/hwmon drivers
+
+	Written by Steve Hardy <steve@linuxrealtime.co.uk>
+
+	Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* The ADS7828 registers */
+#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */
+#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */
+#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */
+#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */
+#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */
+#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */
+#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */
+#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+	I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(ads7828);
+
+/* Other module parameters */
+static int se_input = 1; /* Default is SE, 0 == diff */
+static int int_vref = 1; /* Default is internal ref ON */
+static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */
+module_param(se_input, bool, S_IRUGO);
+module_param(int_vref, bool, S_IRUGO);
+module_param(vref_mv, int, S_IRUGO);
+
+/* Global Variables */
+static u8 ads7828_cmd_byte; /* cmd byte without channel bits */
+static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */
+
+/* Each client has this additional data */
+struct ads7828_data {
+	struct i2c_client client;
+	struct device *hwmon_dev;
+	struct mutex update_lock; /* mutex protect updates */
+	char valid; /* !=0 if following fields are valid */
+	unsigned long last_updated; /* In jiffies */
+	u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */
+};
+
+/* Function declaration - necessary due to function dependencies */
+static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind);
+
+/* The ADS7828 returns the 12-bit sample in two bytes,
+	these are read as a word then byte-swapped */
+static u16 ads7828_read_value(struct i2c_client *client, u8 reg)
+{
+	return swab16(i2c_smbus_read_word_data(client, reg));
+}
+
+static inline u8 channel_cmd_byte(int ch)
+{
+	/* cmd byte C2,C1,C0 - see datasheet */
+	u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4);
+	cmd |= ads7828_cmd_byte;
+	return cmd;
+}
+
+/* Update data for the device (all 8 channels) */
+static struct ads7828_data *ads7828_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ads7828_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+			|| !data->valid) {
+		unsigned int ch;
+		dev_dbg(&client->dev, "Starting ads7828 update\n");
+
+		for (ch = 0; ch < ADS7828_NCH; ch++) {
+			u8 cmd = channel_cmd_byte(ch);
+			data->adc_input[ch] = ads7828_read_value(client, cmd);
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/* sysfs callback function */
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+	char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ads7828_data *data = ads7828_update_device(dev);
+	/* Print value (in mV as specified in sysfs-interface documentation) */
+	return sprintf(buf, "%d\n", (data->adc_input[attr->index] *
+		ads7828_lsb_resol)/1000);
+}
+
+#define in_reg(offset)\
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\
+	NULL, offset)
+
+in_reg(0);
+in_reg(1);
+in_reg(2);
+in_reg(3);
+in_reg(4);
+in_reg(5);
+in_reg(6);
+in_reg(7);
+
+static struct attribute *ads7828_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ads7828_group = {
+	.attrs = ads7828_attributes,
+};
+
+static int ads7828_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, ads7828_detect);
+}
+
+static int ads7828_detach_client(struct i2c_client *client)
+{
+	struct ads7828_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
+	i2c_detach_client(client);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ads7828_driver = {
+	.driver = {
+		.name = "ads7828",
+	},
+	.attach_adapter = ads7828_attach_adapter,
+	.detach_client = ads7828_detach_client,
+};
+
+/* This function is called by i2c_probe */
+static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct ads7828_data *data;
+	int err = 0;
+	const char *name = "";
+
+	/* Check we have a valid client */
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	client structure, even though we cannot fill it completely yet.
+	But it allows us to access ads7828_read_value. */
+	data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &ads7828_driver;
+
+	/* Now, we do the remaining detection. There is no identification
+	dedicated register so attempt to sanity check using knowledge of
+	the chip
+	- Read from the 8 channel addresses
+	- Check the top 4 bits of each result are not set (12 data bits)
+	*/
+	if (kind < 0) {
+		int ch;
+		for (ch = 0; ch < ADS7828_NCH; ch++) {
+			u16 in_data;
+			u8 cmd = channel_cmd_byte(ch);
+			in_data = ads7828_read_value(client, cmd);
+			if (in_data & 0xF000) {
+				printk(KERN_DEBUG
+				"%s : Doesn't look like an ads7828 device\n",
+				__FUNCTION__);
+				goto exit_free;
+			}
+		}
+	}
+
+	/* Determine the chip type - only one kind supported! */
+	if (kind <= 0)
+		kind = ads7828;
+
+	if (kind == ads7828)
+		name = "ads7828";
+
+	/* Fill in the remaining client fields, put it into the global list */
+	strlcpy(client->name, name, I2C_NAME_SIZE);
+
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	err = i2c_attach_client(client);
+	if (err)
+		goto exit_free;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
+	if (err)
+		goto exit_detach;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
+exit_detach:
+	i2c_detach_client(client);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int __init sensors_ads7828_init(void)
+{
+	/* Initialize the command byte according to module parameters */
+	ads7828_cmd_byte = se_input ?
+		ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF;
+	ads7828_cmd_byte |= int_vref ?
+		ADS7828_CMD_PD3 : ADS7828_CMD_PD1;
+
+	/* Calculate the LSB resolution */
+	ads7828_lsb_resol = (vref_mv*1000)/4096;
+
+	return i2c_add_driver(&ads7828_driver);
+}
+
+static void __exit sensors_ads7828_exit(void)
+{
+	i2c_del_driver(&ads7828_driver);
+}
+
+MODULE_AUTHOR("Steve Hardy <steve@linuxrealtime.co.uk>");
+MODULE_DESCRIPTION("ADS7828 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_ads7828_init);
+module_exit(sensors_ads7828_exit);
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 9810aaa..747693a 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -48,7 +48,22 @@
 #define ADT7470_REG_CFG				0x40
 #define		ADT7470_FSPD_MASK		0x04
 #define ADT7470_REG_ALARM1			0x41
+#define		ADT7470_R1T_ALARM		0x01
+#define		ADT7470_R2T_ALARM		0x02
+#define		ADT7470_R3T_ALARM		0x04
+#define		ADT7470_R4T_ALARM		0x08
+#define		ADT7470_R5T_ALARM		0x10
+#define		ADT7470_R6T_ALARM		0x20
+#define		ADT7470_R7T_ALARM		0x40
+#define		ADT7470_OOL_ALARM		0x80
 #define ADT7470_REG_ALARM2			0x42
+#define		ADT7470_R8T_ALARM		0x01
+#define		ADT7470_R9T_ALARM		0x02
+#define		ADT7470_R10T_ALARM		0x04
+#define		ADT7470_FAN1_ALARM		0x10
+#define		ADT7470_FAN2_ALARM		0x20
+#define		ADT7470_FAN3_ALARM		0x40
+#define		ADT7470_FAN4_ALARM		0x80
 #define ADT7470_REG_TEMP_LIMITS_BASE_ADDR	0x44
 #define ADT7470_REG_TEMP_LIMITS_MAX_ADDR	0x57
 #define ADT7470_REG_FAN_MIN_BASE_ADDR		0x58
@@ -97,6 +112,8 @@
 #define ADT7470_REG_PWM_AUTO_TEMP(x)	(ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR + \
 					((x) / 2))
 
+#define ALARM2(x)		((x) << 8)
+
 #define ADT7470_VENDOR		0x41
 #define ADT7470_DEVICE		0x70
 /* datasheet only mentions a revision 2 */
@@ -114,8 +131,6 @@
 /* sleep 1s while gathering temperature data */
 #define TEMP_COLLECTION_TIME	1000
 
-#define power_of_2(x)	(((x) & ((x) - 1)) == 0)
-
 /* datasheet says to divide this number by the fan reading to get fan rpm */
 #define FAN_PERIOD_TO_RPM(x)	((90000 * 60) / (x))
 #define FAN_RPM_TO_PERIOD	FAN_PERIOD_TO_RPM
@@ -138,7 +153,8 @@
 	u16			fan[ADT7470_FAN_COUNT];
 	u16			fan_min[ADT7470_FAN_COUNT];
 	u16			fan_max[ADT7470_FAN_COUNT];
-	u16			alarms, alarms_mask;
+	u16			alarm;
+	u16			alarms_mask;
 	u8			force_pwm_max;
 	u8			pwm[ADT7470_PWM_COUNT];
 	u8			pwm_max[ADT7470_PWM_COUNT];
@@ -262,7 +278,10 @@
 	else
 		data->force_pwm_max = 0;
 
-	data->alarms = adt7470_read_word_data(client, ADT7470_REG_ALARM1);
+	data->alarm = i2c_smbus_read_byte_data(client, ADT7470_REG_ALARM1);
+	if (data->alarm & ADT7470_OOL_ALARM)
+		data->alarm |= ALARM2(i2c_smbus_read_byte_data(client,
+							ADT7470_REG_ALARM2));
 	data->alarms_mask = adt7470_read_word_data(client,
 						   ADT7470_REG_ALARM1_MASK);
 
@@ -370,17 +389,13 @@
 	return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]);
 }
 
-static ssize_t show_alarms(struct device *dev,
+static ssize_t show_alarm_mask(struct device *dev,
 			   struct device_attribute *devattr,
 			   char *buf)
 {
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adt7470_data *data = adt7470_update_device(dev);
 
-	if (attr->index)
-		return sprintf(buf, "%x\n", data->alarms);
-	else
-		return sprintf(buf, "%x\n", data->alarms_mask);
+	return sprintf(buf, "%x\n", data->alarms_mask);
 }
 
 static ssize_t show_fan_max(struct device *dev,
@@ -677,7 +692,7 @@
 {
 	if (input == ADT7470_PWM_ALL_TEMPS)
 		return 0;
-	if (input < 1 || !power_of_2(input))
+	if (input < 1 || !is_power_of_2(input))
 		return -EINVAL;
 	return ilog2(input) + 1;
 }
@@ -715,8 +730,20 @@
 	return count;
 }
 
-static SENSOR_DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL, 0);
-static SENSOR_DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarms, NULL, 1);
+static ssize_t show_alarm(struct device *dev,
+			  struct device_attribute *devattr,
+			  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct adt7470_data *data = adt7470_update_device(dev);
+
+	if (data->alarm & attr->index)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL);
 
 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
 		    set_temp_max, 0);
@@ -771,6 +798,27 @@
 static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8);
 static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp, NULL, 9);
 
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R1T_ALARM);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R2T_ALARM);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R3T_ALARM);
+static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R4T_ALARM);
+static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R5T_ALARM);
+static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R6T_ALARM);
+static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO, show_alarm, NULL,
+			  ADT7470_R7T_ALARM);
+static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_R8T_ALARM));
+static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_R9T_ALARM));
+static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_R10T_ALARM));
+
 static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max,
 		    set_fan_max, 0);
 static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max,
@@ -794,6 +842,15 @@
 static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
 static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
 
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_FAN1_ALARM));
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_FAN2_ALARM));
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_FAN3_ALARM));
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL,
+			  ALARM2(ADT7470_FAN4_ALARM));
+
 static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO,
 		    show_force_pwm_max, set_force_pwm_max, 0);
 
@@ -858,8 +915,7 @@
 
 static struct attribute *adt7470_attr[] =
 {
-	&sensor_dev_attr_alarms.dev_attr.attr,
-	&sensor_dev_attr_alarm_mask.dev_attr.attr,
+	&dev_attr_alarm_mask.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp2_max.dev_attr.attr,
 	&sensor_dev_attr_temp3_max.dev_attr.attr,
@@ -890,6 +946,16 @@
 	&sensor_dev_attr_temp8_input.dev_attr.attr,
 	&sensor_dev_attr_temp9_input.dev_attr.attr,
 	&sensor_dev_attr_temp10_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp5_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp6_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp7_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp8_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp9_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp10_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan1_max.dev_attr.attr,
 	&sensor_dev_attr_fan2_max.dev_attr.attr,
 	&sensor_dev_attr_fan3_max.dev_attr.attr,
@@ -902,6 +968,10 @@
 	&sensor_dev_attr_fan2_input.dev_attr.attr,
 	&sensor_dev_attr_fan3_input.dev_attr.attr,
 	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
 	&sensor_dev_attr_force_pwm_max.dev_attr.attr,
 	&sensor_dev_attr_pwm1.dev_attr.attr,
 	&sensor_dev_attr_pwm2.dev_attr.attr,
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 9460dba..950cea8 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -47,12 +48,6 @@
 #include <linux/mutex.h>
 #include "lm75.h"
 
-/*
-	HISTORY:
-	2003-12-29	1.0.0	Ported from lm_sensors project for kernel 2.6
-*/
-#define ASB100_VERSION "1.0.0"
-
 /* I2C addresses to scan */
 static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 
@@ -221,15 +216,16 @@
 	.driver = {
 		.name	= "asb100",
 	},
-	.id		= I2C_DRIVERID_ASB100,
 	.attach_adapter	= asb100_attach_adapter,
 	.detach_client	= asb100_detach_client,
 };
 
 /* 7 Voltages */
 #define show_in_reg(reg) \
-static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+		char *buf) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct asb100_data *data = asb100_update_device(dev); \
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
 }
@@ -239,9 +235,10 @@
 show_in_reg(in_max)
 
 #define set_in_reg(REG, reg) \
-static ssize_t set_in_##reg(struct device *dev, const char *buf, \
-		size_t count, int nr) \
+static ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \
+		const char *buf, size_t count) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct asb100_data *data = i2c_get_clientdata(client); \
 	unsigned long val = simple_strtoul(buf, NULL, 10); \
@@ -258,37 +255,12 @@
 set_in_reg(MAX, max)
 
 #define sysfs_in(offset) \
-static ssize_t \
-	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_in(dev, buf, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
-		show_in##offset, NULL); \
-static ssize_t \
-	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_in_min(dev, buf, offset); \
-} \
-static ssize_t \
-	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_in_max(dev, buf, offset); \
-} \
-static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
-		const char *buf, size_t count) \
-{ \
-	return set_in_min(dev, buf, count, offset); \
-} \
-static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
-		const char *buf, size_t count) \
-{ \
-	return set_in_max(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
-		show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
-		show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+		show_in, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+		show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+		show_in_max, set_in_max, offset)
 
 sysfs_in(0);
 sysfs_in(1);
@@ -299,29 +271,36 @@
 sysfs_in(6);
 
 /* 3 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 		DIV_FROM_REG(data->fan_div[nr])));
 }
 
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
 		DIV_FROM_REG(data->fan_div[nr])));
 }
 
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
 
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-				size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
 	u32 val = simple_strtoul(buf, NULL, 10);
@@ -337,22 +316,23 @@
    determined in part by the fan divisor.  This follows the principle of
    least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-				size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
 	unsigned long min;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int reg;
-	
+
 	mutex_lock(&data->update_lock);
 
 	min = FAN_FROM_REG(data->fan_min[nr],
 			DIV_FROM_REG(data->fan_div[nr]));
 	data->fan_div[nr] = DIV_TO_REG(val);
 
-	switch(nr) {
+	switch (nr) {
 	case 0:	/* fan 1 */
 		reg = asb100_read_value(client, ASB100_REG_VID_FANDIV);
 		reg = (reg & 0xcf) | (data->fan_div[0] << 4);
@@ -382,34 +362,12 @@
 }
 
 #define sysfs_fan(offset) \
-static ssize_t show_fan##offset(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_fan(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_fan_min(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_fan_div(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-					size_t count) \
-{ \
-	return set_fan_min(dev, buf, count, offset - 1); \
-} \
-static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \
-					size_t count) \
-{ \
-	return set_fan_div(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
-		show_fan##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
-		show_fan##offset##_min, set_fan##offset##_min); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
-		show_fan##offset##_div, set_fan##offset##_div);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+		show_fan, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+		show_fan_min, set_fan_min, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+		show_fan_div, set_fan_div, offset - 1)
 
 sysfs_fan(1);
 sysfs_fan(2);
@@ -430,10 +388,12 @@
 	}
 	return ret;
 }
-		 	
+
 #define show_temp_reg(reg) \
-static ssize_t show_##reg(struct device *dev, char *buf, int nr) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+		char *buf) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct asb100_data *data = asb100_update_device(dev); \
 	return sprintf_temp_from_reg(data->reg[nr], buf, nr); \
 }
@@ -443,9 +403,10 @@
 show_temp_reg(temp_hyst);
 
 #define set_temp_reg(REG, reg) \
-static ssize_t set_##reg(struct device *dev, const char *buf, \
-			size_t count, int nr) \
+static ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \
+		const char *buf, size_t count) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct asb100_data *data = i2c_get_clientdata(client); \
 	long val = simple_strtol(buf, NULL, 10); \
@@ -469,33 +430,12 @@
 set_temp_reg(HYST, temp_hyst);
 
 #define sysfs_temp(num) \
-static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_temp(dev, buf, num-1); \
-} \
-static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL); \
-static ssize_t show_temp_max##num(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_temp_max(dev, buf, num-1); \
-} \
-static ssize_t set_temp_max##num(struct device *dev, struct device_attribute *attr, const char *buf, \
-					size_t count) \
-{ \
-	return set_temp_max(dev, buf, count, num-1); \
-} \
-static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
-		show_temp_max##num, set_temp_max##num); \
-static ssize_t show_temp_hyst##num(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_temp_hyst(dev, buf, num-1); \
-} \
-static ssize_t set_temp_hyst##num(struct device *dev, struct device_attribute *attr, const char *buf, \
-					size_t count) \
-{ \
-	return set_temp_hyst(dev, buf, count, num-1); \
-} \
-static DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \
-		show_temp_hyst##num, set_temp_hyst##num);
+static SENSOR_DEVICE_ATTR(temp##num##_input, S_IRUGO, \
+		show_temp, NULL, num - 1); \
+static SENSOR_DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
+		show_temp_max, set_temp_max, num - 1); \
+static SENSOR_DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \
+		show_temp_hyst, set_temp_hyst, num - 1)
 
 sysfs_temp(1);
 sysfs_temp(2);
@@ -503,7 +443,8 @@
 sysfs_temp(4);
 
 /* VID */
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
@@ -512,25 +453,26 @@
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 /* VRM */
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct asb100_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%d\n", data->vrm);
 }
 
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct asb100_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
-	data->vrm = val;
+	struct asb100_data *data = dev_get_drvdata(dev);
+	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
 
 /* Alarms */
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
@@ -538,14 +480,35 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct asb100_data *data = asb100_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
+
 /* 1 PWM */
-static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f));
 }
 
-static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
@@ -559,14 +522,15 @@
 	return count;
 }
 
-static ssize_t show_pwm_enable1(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_pwm_enable1(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0);
 }
 
-static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr, const char *buf,
-				size_t count)
+static ssize_t set_pwm_enable1(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
@@ -585,50 +549,62 @@
 		show_pwm_enable1, set_pwm_enable1);
 
 static struct attribute *asb100_attributes[] = {
-	&dev_attr_in0_input.attr,
-	&dev_attr_in0_min.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in1_min.attr,
-	&dev_attr_in1_max.attr,
-	&dev_attr_in2_input.attr,
-	&dev_attr_in2_min.attr,
-	&dev_attr_in2_max.attr,
-	&dev_attr_in3_input.attr,
-	&dev_attr_in3_min.attr,
-	&dev_attr_in3_max.attr,
-	&dev_attr_in4_input.attr,
-	&dev_attr_in4_min.attr,
-	&dev_attr_in4_max.attr,
-	&dev_attr_in5_input.attr,
-	&dev_attr_in5_min.attr,
-	&dev_attr_in5_max.attr,
-	&dev_attr_in6_input.attr,
-	&dev_attr_in6_min.attr,
-	&dev_attr_in6_max.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
 
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_fan1_div.attr,
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_fan2_div.attr,
-	&dev_attr_fan3_input.attr,
-	&dev_attr_fan3_min.attr,
-	&dev_attr_fan3_div.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_div.dev_attr.attr,
 
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp1_max.attr,
-	&dev_attr_temp1_max_hyst.attr,
-	&dev_attr_temp2_input.attr,
-	&dev_attr_temp2_max.attr,
-	&dev_attr_temp2_max_hyst.attr,
-	&dev_attr_temp3_input.attr,
-	&dev_attr_temp3_max.attr,
-	&dev_attr_temp3_max_hyst.attr,
-	&dev_attr_temp4_input.attr,
-	&dev_attr_temp4_max.attr,
-	&dev_attr_temp4_max_hyst.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
+
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
 
 	&dev_attr_cpu0_vid.attr,
 	&dev_attr_vrm.attr,
@@ -656,10 +632,10 @@
 }
 
 static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
-		int kind, struct i2c_client *new_client)
+		int kind, struct i2c_client *client)
 {
 	int i, id, err;
-	struct asb100_data *data = i2c_get_clientdata(new_client);
+	struct asb100_data *data = i2c_get_clientdata(client);
 
 	data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!(data->lm75[0])) {
@@ -679,26 +655,26 @@
 		for (i = 2; i <= 3; i++) {
 			if (force_subclients[i] < 0x48 ||
 			    force_subclients[i] > 0x4f) {
-				dev_err(&new_client->dev, "invalid subclient "
+				dev_err(&client->dev, "invalid subclient "
 					"address %d; must be 0x48-0x4f\n",
 					force_subclients[i]);
 				err = -ENODEV;
 				goto ERROR_SC_2;
 			}
 		}
-		asb100_write_value(new_client, ASB100_REG_I2C_SUBADDR,
+		asb100_write_value(client, ASB100_REG_I2C_SUBADDR,
 					(force_subclients[2] & 0x07) |
-					((force_subclients[3] & 0x07) <<4));
+					((force_subclients[3] & 0x07) << 4));
 		data->lm75[0]->addr = force_subclients[2];
 		data->lm75[1]->addr = force_subclients[3];
 	} else {
-		int val = asb100_read_value(new_client, ASB100_REG_I2C_SUBADDR);
+		int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR);
 		data->lm75[0]->addr = 0x48 + (val & 0x07);
 		data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07);
 	}
 
-	if(data->lm75[0]->addr == data->lm75[1]->addr) {
-		dev_err(&new_client->dev, "duplicate addresses 0x%x "
+	if (data->lm75[0]->addr == data->lm75[1]->addr) {
+		dev_err(&client->dev, "duplicate addresses 0x%x "
 				"for subclients\n", data->lm75[0]->addr);
 		err = -ENODEV;
 		goto ERROR_SC_2;
@@ -708,18 +684,17 @@
 		i2c_set_clientdata(data->lm75[i], NULL);
 		data->lm75[i]->adapter = adapter;
 		data->lm75[i]->driver = &asb100_driver;
-		data->lm75[i]->flags = 0;
 		strlcpy(data->lm75[i]->name, "asb100 subclient", I2C_NAME_SIZE);
 	}
 
 	if ((err = i2c_attach_client(data->lm75[0]))) {
-		dev_err(&new_client->dev, "subclient %d registration "
+		dev_err(&client->dev, "subclient %d registration "
 			"at address 0x%x failed.\n", i, data->lm75[0]->addr);
 		goto ERROR_SC_2;
 	}
 
 	if ((err = i2c_attach_client(data->lm75[1]))) {
-		dev_err(&new_client->dev, "subclient %d registration "
+		dev_err(&client->dev, "subclient %d registration "
 			"at address 0x%x failed.\n", i, data->lm75[1]->addr);
 		goto ERROR_SC_3;
 	}
@@ -740,7 +715,7 @@
 static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int err;
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct asb100_data *data;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -760,13 +735,12 @@
 		goto ERROR0;
 	}
 
-	new_client = &data->client;
+	client = &data->client;
 	mutex_init(&data->lock);
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &asb100_driver;
-	new_client->flags = 0;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &asb100_driver;
 
 	/* Now, we do the remaining detection. */
 
@@ -776,15 +750,15 @@
 	   bank. */
 	if (kind < 0) {
 
-		int val1 = asb100_read_value(new_client, ASB100_REG_BANK);
-		int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN);
+		int val1 = asb100_read_value(client, ASB100_REG_BANK);
+		int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN);
 
 		/* If we're in bank 0 */
-		if ( (!(val1 & 0x07)) &&
+		if ((!(val1 & 0x07)) &&
 				/* Check for ASB100 ID (low byte) */
-				( ((!(val1 & 0x80)) && (val2 != 0x94)) ||
+				(((!(val1 & 0x80)) && (val2 != 0x94)) ||
 				/* Check for ASB100 ID (high byte ) */
-				((val1 & 0x80) && (val2 != 0x06)) ) ) {
+				((val1 & 0x80) && (val2 != 0x06)))) {
 			pr_debug("asb100.o: detect failed, "
 					"bad chip id 0x%02x!\n", val2);
 			err = -ENODEV;
@@ -795,19 +769,19 @@
 
 	/* We have either had a force parameter, or we have already detected
 	   Winbond. Put it now into bank 0 and Vendor ID High Byte */
-	asb100_write_value(new_client, ASB100_REG_BANK,
-		(asb100_read_value(new_client, ASB100_REG_BANK) & 0x78) | 0x80);
+	asb100_write_value(client, ASB100_REG_BANK,
+		(asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80);
 
 	/* Determine the chip type. */
 	if (kind <= 0) {
-		int val1 = asb100_read_value(new_client, ASB100_REG_WCHIPID);
-		int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN);
+		int val1 = asb100_read_value(client, ASB100_REG_WCHIPID);
+		int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN);
 
 		if ((val1 == 0x31) && (val2 == 0x06))
 			kind = asb100;
 		else {
 			if (kind == 0)
-				dev_warn(&new_client->dev, "ignoring "
+				dev_warn(&client->dev, "ignoring "
 					"'force' parameter for unknown chip "
 					"at adapter %d, address 0x%02x.\n",
 					i2c_adapter_id(adapter), address);
@@ -817,34 +791,32 @@
 	}
 
 	/* Fill in remaining client fields and put it into the global list */
-	strlcpy(new_client->name, "asb100", I2C_NAME_SIZE);
+	strlcpy(client->name, "asb100", I2C_NAME_SIZE);
 	data->type = kind;
-
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto ERROR1;
 
 	/* Attach secondary lm75 clients */
 	if ((err = asb100_detect_subclients(adapter, address, kind,
-			new_client)))
+			client)))
 		goto ERROR2;
 
 	/* Initialize the chip */
-	asb100_init_client(new_client);
+	asb100_init_client(client);
 
 	/* A few vars need to be filled upon startup */
-	data->fan_min[0] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(0));
-	data->fan_min[1] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(1));
-	data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
+	data->fan_min[0] = asb100_read_value(client, ASB100_REG_FAN_MIN(0));
+	data->fan_min[1] = asb100_read_value(client, ASB100_REG_FAN_MIN(1));
+	data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &asb100_group)))
 		goto ERROR3;
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto ERROR4;
@@ -853,14 +825,14 @@
 	return 0;
 
 ERROR4:
-	sysfs_remove_group(&new_client->dev.kobj, &asb100_group);
+	sysfs_remove_group(&client->dev.kobj, &asb100_group);
 ERROR3:
 	i2c_detach_client(data->lm75[1]);
 	i2c_detach_client(data->lm75[0]);
 	kfree(data->lm75[1]);
 	kfree(data->lm75[0]);
 ERROR2:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 ERROR1:
 	kfree(data);
 ERROR0:
@@ -916,17 +888,17 @@
 		/* convert from ISA to LM75 I2C addresses */
 		switch (reg & 0xff) {
 		case 0x50: /* TEMP */
-			res = swab16(i2c_smbus_read_word_data (cl, 0));
+			res = swab16(i2c_smbus_read_word_data(cl, 0));
 			break;
 		case 0x52: /* CONFIG */
 			res = i2c_smbus_read_byte_data(cl, 1);
 			break;
 		case 0x53: /* HYST */
-			res = swab16(i2c_smbus_read_word_data (cl, 2));
+			res = swab16(i2c_smbus_read_word_data(cl, 2));
 			break;
 		case 0x55: /* MAX */
 		default:
-			res = swab16(i2c_smbus_read_word_data (cl, 3));
+			res = swab16(i2c_smbus_read_word_data(cl, 3));
 			break;
 		}
 	}
@@ -989,7 +961,7 @@
 	vid = vid_from_reg(vid, data->vrm);
 
 	/* Start monitoring */
-	asb100_write_value(client, ASB100_REG_CONFIG, 
+	asb100_write_value(client, ASB100_REG_CONFIG,
 		(asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01);
 }
 
@@ -1078,4 +1050,3 @@
 
 module_init(asb100_init);
 module_exit(asb100_exit);
-
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index a878c98..ddddd9f 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -44,6 +44,10 @@
 module_param(force_start, bool, 0);
 MODULE_PARM_DESC(force_start, "Force the chip to start monitoring inputs");
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};
 
@@ -279,14 +283,21 @@
 /* Fan input RPM */
 static inline int FAN_FROM_REG(int reg, int tpc)
 {
-	return (reg == 0 || reg == 0xffff) ? 0 :
-		(tpc == 0) ? 90000 * 60 / reg : tpc * reg;
+	if (tpc) {
+		return tpc * reg;
+	} else {
+		return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg;
+	}
 }
 
 static inline int FAN_TO_REG(int val, int tpc)
 {
-	return SENSORS_LIMIT((tpc == 0) ? 90000 * 60 / val : val / tpc,
-			     0, 0xffff);
+	if (tpc) {
+		return SENSORS_LIMIT(val / tpc, 0, 0xffff);
+	} else {
+		return (val <= 0) ? 0xffff :
+			SENSORS_LIMIT(90000 * 60 / val, 0, 0xfffe);
+	}
 }
 
 /* Fan TPC (tach pulse count)
@@ -2019,7 +2030,7 @@
 
 	/* Check device ID
 	 * The DME1737 can return either 0x78 or 0x77 as its device ID. */
-	reg = dme1737_sio_inb(sio_cip, 0x20);
+	reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20);
 	if (!(reg == 0x77 || reg == 0x78)) {
 		err = -ENODEV;
 		goto exit;
@@ -2191,7 +2202,7 @@
 	/* Check device ID
 	 * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and
 	 * SCH3116 (0x7f). */
-	reg = dme1737_sio_inb(sio_cip, 0x20);
+	reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20);
 	if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {
 		err = -ENODEV;
 		goto exit;
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index b7bd000..3f5163d 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -94,7 +94,6 @@
 	.driver = {
 		.name	= "ds1621",
 	},
-	.id		= I2C_DRIVERID_DS1621,
 	.attach_adapter	= ds1621_attach_adapter,
 	.detach_client	= ds1621_detach_client,
 };
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 5d9d5cc..7a14a2d 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -41,6 +41,10 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define DRVNAME "f71805f"
@@ -1497,7 +1501,7 @@
 	if (devid != SIO_FINTEK_ID)
 		goto exit;
 
-	devid = superio_inw(sioaddr, SIO_REG_DEVID);
+	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
 	switch (devid) {
 	case SIO_F71805F_ID:
 		sio_data->kind = f71805f;
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 6db7443..cbeb498 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -74,6 +74,10 @@
 
 #define FAN_MIN_DETECT			366 /* Lowest detectable fanspeed */
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *f71882fg_pdev = NULL;
 
 /* Super-I/O Function prototypes */
@@ -843,7 +847,7 @@
 		goto exit;
 	}
 
-	devid = superio_inw(sioaddr, SIO_REG_DEVID);
+	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
 	if (devid != SIO_F71882_ID) {
 		printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
 		goto exit;
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index e67c369..721c701 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -123,7 +123,6 @@
 	.driver = {
 		.name	= "fscher",
 	},
-	.id		= I2C_DRIVERID_FSCHER,
 	.attach_adapter	= fscher_attach_adapter,
 	.detach_client	= fscher_detach_client,
 };
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index 63a4df0..b7c9eef 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -41,6 +41,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
+#include <linux/dmi.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
@@ -133,7 +134,7 @@
 	{ 0x71, 0x81, 0x91 },				/* her */
 	{ 0x71, 0xd1, 0x81, 0x91 },			/* scy */
 	{ 0x71, 0x81, 0x91 },				/* hrc */
-	{ 0x71, 0x81, 0x91, 0xd1, 0xe1 },		/* hmd */
+	{ 0x71, 0x81, 0x91, 0xd1, 0xe1 },		/* hmd */
 };
 
 /* temperature high limit registers, FSC does not document these. Proven to be
@@ -146,7 +147,7 @@
 	{ 0x76, 0x86, 0x96 },				/* her */
 	{ 0x76, 0xd6, 0x86, 0x96 },			/* scy */
 	{ 0x76, 0x86, 0x96 },				/* hrc */
-	{ 0x76, 0x86, 0x96, 0xd6, 0xe6 },		/* hmd */
+	{ 0x76, 0x86, 0x96, 0xd6, 0xe6 },		/* hmd */
 };
 
 /* These were found through experimenting with an fscher, currently they are
@@ -210,6 +211,13 @@
 	u8 fan_ripple[6];	/* divider for rps */
 };
 
+/* Global variables to hold information read from special DMI tables, which are
+   available on FSC machines with an fscher or later chip. */
+static int dmi_mult[3] = { 490, 200, 100 };
+static int dmi_offset[3] = { 0, 0, 0 };
+static int dmi_vref = -1;
+
+
 /*
  * Sysfs attr show / store functions
  */
@@ -221,8 +229,13 @@
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct fschmd_data *data = fschmd_update_device(dev);
 
-	return sprintf(buf, "%d\n", (data->volt[index] *
-		max_reading[index] + 128) / 255);
+	/* fscher / fschrc - 1 as data->kind is an array index, not a chips */
+	if (data->kind == (fscher - 1) || data->kind >= (fschrc - 1))
+		return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref *
+			dmi_mult[index]) / 255 + dmi_offset[index]);
+	else
+		return sprintf(buf, "%d\n", (data->volt[index] *
+			max_reading[index] + 128) / 255);
 }
 
 
@@ -525,6 +538,68 @@
  * Real code
  */
 
+/* DMI decode routine to read voltage scaling factors from special DMI tables,
+   which are available on FSC machines with an fscher or later chip. */
+static void fschmd_dmi_decode(const struct dmi_header *header)
+{
+	int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0;
+
+	/* dmi code ugliness, we get passed the address of the contents of
+	   a complete DMI record, but in the form of a dmi_header pointer, in
+	   reality this address holds header->length bytes of which the header
+	   are the first 4 bytes */
+	u8 *dmi_data = (u8 *)header;
+
+	/* We are looking for OEM-specific type 185 */
+	if (header->type != 185)
+		return;
+
+	/* we are looking for what Siemens calls "subtype" 19, the subtype
+	   is stored in byte 5 of the dmi block */
+	if (header->length < 5 || dmi_data[4] != 19)
+		return;
+
+	/* After the subtype comes 1 unknown byte and then blocks of 5 bytes,
+	   consisting of what Siemens calls an "Entity" number, followed by
+	   2 16-bit words in LSB first order */
+	for (i = 6; (i + 4) < header->length; i += 5) {
+		/* entity 1 - 3: voltage multiplier and offset */
+		if (dmi_data[i] >= 1 && dmi_data[i] <= 3) {
+			/* Our in sensors order and the DMI order differ */
+			const int shuffle[3] = { 1, 0, 2 };
+			int in = shuffle[dmi_data[i] - 1];
+
+			/* Check for twice the same entity */
+			if (found & (1 << in))
+				return;
+
+			mult[in] = dmi_data[i + 1] | (dmi_data[i + 2] << 8);
+			offset[in] = dmi_data[i + 3] | (dmi_data[i + 4] << 8);
+
+			found |= 1 << in;
+		}
+
+		/* entity 7: reference voltage */
+		if (dmi_data[i] == 7) {
+			/* Check for twice the same entity */
+			if (found & 0x08)
+				return;
+
+			vref = dmi_data[i + 1] | (dmi_data[i + 2] << 8);
+
+			found |= 0x08;
+		}
+	}
+
+	if (found == 0x0F) {
+		for (i = 0; i < 3; i++) {
+			dmi_mult[i] = mult[i] * 10;
+			dmi_offset[i] = offset[i] * 10;
+		}
+		dmi_vref = vref;
+	}
+}
+
 static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *client;
@@ -586,6 +661,17 @@
 		data->temp_max[2] = 50 + 128;
 	}
 
+	/* Read the special DMI table for fscher and newer chips */
+	if (kind == fscher || kind >= fschrc) {
+		dmi_walk(fschmd_dmi_decode);
+		if (dmi_vref == -1) {
+			printk(KERN_WARNING FSCHMD_NAME
+				": Couldn't get voltage scaling factors from "
+				"BIOS DMI table, using builtin defaults\n");
+			dmi_vref = 33;
+		}
+	}
+
 	/* i2c kind goes from 1-5, we want from 0-4 to address arrays */
 	data->kind = kind - 1;
 	strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE);
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 92c9703..2f10753 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -105,7 +105,6 @@
 	.driver = {
 		.name	= "fscpos",
 	},
-	.id		= I2C_DRIVERID_FSCPOS,
 	.attach_adapter	= fscpos_attach_adapter,
 	.detach_client	= fscpos_detach_client,
 };
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index bb58d98..3b1ac48 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -30,10 +30,6 @@
  * We did not keep that part of the original driver in the Linux 2.6
  * version, since it was making the driver significantly more complex
  * with no real benefit.
- *
- * History:
- * 2004-01-28  Original port. (Hong-Gunn Chew)
- * 2004-01-31  Code review and approval. (Jean Delvare)
  */
 
 #include <linux/module.h>
@@ -42,6 +38,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
@@ -99,10 +96,10 @@
 	long rpmdiv;
 	if (rpm == 0)
 		return 0;
-	rpmdiv = SENSORS_LIMIT(rpm, 1, 1920000) * div;
-	return SENSORS_LIMIT((960000 + rpmdiv / 2) / rpmdiv, 1, 255);
+	rpmdiv = SENSORS_LIMIT(rpm, 1, 960000) * div;
+	return SENSORS_LIMIT((480000 + rpmdiv / 2) / rpmdiv, 1, 255);
 }
-#define FAN_FROM_REG(val,div)	((val)==0 ? 0 : (960000/((val)*(div))))
+#define FAN_FROM_REG(val,div)	((val)==0 ? 0 : (480000/((val)*(div))))
 
 #define IN_TO_REG(val)		(SENSORS_LIMIT((((val)+9)/19),0,255))
 #define IN_FROM_REG(val)	((val)*19)
@@ -110,7 +107,6 @@
 #define VDD_TO_REG(val)		(SENSORS_LIMIT((((val)*4+47)/95),0,255))
 #define VDD_FROM_REG(val)	(((val)*95+2)/4)
 
-#define DIV_TO_REG(val)		((val)==4?2:(val)==2?1:(val)==1?0:3)
 #define DIV_FROM_REG(val)	(1 << (val))
 
 #define BEEP_MASK_TO_REG(val)	((val) & 0x7f & data->alarm_mask)
@@ -129,7 +125,6 @@
 	u8 voltage_in[4];	/* Register values; [0] = VDD */
 	u8 voltage_min[4];	/* Register values; [0] = VDD */
 	u8 voltage_max[4];	/* Register values; [0] = VDD */
-	u8 iter_voltage_in[4];	/* Register values; [0] = VDD */
 	u8 fan_in[2];
 	u8 fan_min[2];
 	u8 fan_div[2];		/* Register encoding, shifted right */
@@ -138,7 +133,7 @@
 	u8 temp_max;		/* Register values */
 	u8 temp_hyst;		/* Register values */
 	u8 alarms;		/* Register value */
-	u8 alarm_mask;		/* Register value */
+	u8 alarm_mask;
 	u8 beep_mask;		/* Register value */
 	u8 beep_enable;		/* Boolean */
 };
@@ -156,7 +151,6 @@
 	.driver = {
 		.name	= "gl518sm",
 	},
-	.id		= I2C_DRIVERID_GL518,
 	.attach_adapter	= gl518_attach_adapter,
 	.detach_client	= gl518_detach_client,
 };
@@ -172,24 +166,10 @@
 	return sprintf(buf, "%d\n", type##_FROM_REG(data->value));	\
 }
 
-#define show_fan(suffix, value, index)					\
-static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf)		\
-{									\
-	struct gl518_data *data = gl518_update_device(dev);		\
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[index],	\
-		DIV_FROM_REG(data->fan_div[index])));			\
-}
-
 show(TEMP, temp_input1, temp_in);
 show(TEMP, temp_max1, temp_max);
 show(TEMP, temp_hyst1, temp_hyst);
 show(BOOL, fan_auto1, fan_auto1);
-show_fan(fan_input1, fan_in, 0);
-show_fan(fan_input2, fan_in, 1);
-show_fan(fan_min1, fan_min, 0);
-show_fan(fan_min2, fan_min, 1);
-show(DIV, fan_div1, fan_div[0]);
-show(DIV, fan_div2, fan_div[1]);
 show(VDD, in_input0, voltage_in[0]);
 show(IN, in_input1, voltage_in[1]);
 show(IN, in_input2, voltage_in[2]);
@@ -206,6 +186,32 @@
 show(BOOL, beep_enable, beep_enable);
 show(BEEP_MASK, beep_mask, beep_mask);
 
+static ssize_t show_fan_input(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct gl518_data *data = gl518_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_in[nr],
+					DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_min(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct gl518_data *data = gl518_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+					DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_div(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct gl518_data *data = gl518_update_device(dev);
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
 #define set(type, suffix, value, reg)					\
 static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
 	size_t count)							\
@@ -247,8 +253,6 @@
 set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX);
 set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST);
 set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3);
-set_bits(DIV, fan_div1, fan_div[0], GL518_REG_MISC, 0xc0, 6);
-set_bits(DIV, fan_div2, fan_div[1], GL518_REG_MISC, 0x30, 4);
 set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT);
 set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT);
 set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT);
@@ -260,25 +264,27 @@
 set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2);
 set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
 
-static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl518_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int regvalue;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT);
-	data->fan_min[0] = FAN_TO_REG(val,
-		DIV_FROM_REG(data->fan_div[0]));
-	regvalue = (regvalue & 0x00ff) | (data->fan_min[0] << 8);
+	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+	regvalue = (regvalue & (0xff << (8 * nr)))
+		 | (data->fan_min[nr] << (8 * (1 - nr)));
 	gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
 
 	data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
-	if (data->fan_min[0] == 0)
-		data->alarm_mask &= ~0x20;
+	if (data->fan_min[nr] == 0)
+		data->alarm_mask &= ~(0x20 << nr);
 	else
-		data->alarm_mask |= 0x20;
+		data->alarm_mask |= (0x20 << nr);
 	data->beep_mask &= data->alarm_mask;
 	gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
 
@@ -286,28 +292,32 @@
 	return count;
 }
 
-static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl518_data *data = i2c_get_clientdata(client);
+	int nr = to_sensor_dev_attr(attr)->index;
 	int regvalue;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
+	switch (val) {
+	case 1: val = 0; break;
+	case 2: val = 1; break;
+	case 4: val = 2; break;
+	case 8: val = 3; break;
+	default:
+		dev_err(dev, "Invalid fan clock divider %lu, choose one "
+			"of 1, 2, 4 or 8\n", val);
+		return -EINVAL;
+	}
+
 	mutex_lock(&data->update_lock);
-	regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT);
-	data->fan_min[1] = FAN_TO_REG(val,
-		DIV_FROM_REG(data->fan_div[1]));
-	regvalue = (regvalue & 0xff00) | data->fan_min[1];
-	gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
-
-	data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
-	if (data->fan_min[1] == 0)
-		data->alarm_mask &= ~0x40;
-	else
-		data->alarm_mask |= 0x40;
-	data->beep_mask &= data->alarm_mask;
-	gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
-
+	regvalue = gl518_read_value(client, GL518_REG_MISC);
+	data->fan_div[nr] = val;
+	regvalue = (regvalue & ~(0xc0 >> (2 * nr)))
+		 | (data->fan_div[nr] << (6 - 2 * nr));
+	gl518_write_value(client, GL518_REG_MISC, regvalue);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -317,12 +327,16 @@
 static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO,
 	show_temp_hyst1, set_temp_hyst1);
 static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1);
-static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL);
-static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL);
-static DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, show_fan_min1, set_fan_min1);
-static DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, show_fan_min2, set_fan_min2);
-static DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, show_fan_div1, set_fan_div1);
-static DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, show_fan_div2, set_fan_div2);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO,
+	show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO,
+	show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO,
+	show_fan_div, set_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO,
+	show_fan_div, set_fan_div, 1);
 static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);
 static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);
 static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);
@@ -341,10 +355,62 @@
 static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO,
 	show_beep_mask, set_beep_mask);
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct gl518_data *data = gl518_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6);
+
+static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct gl518_data *data = gl518_update_device(dev);
+	return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
+}
+
+static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl518_data *data = i2c_get_clientdata(client);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	unsigned long bit;
+
+	bit = simple_strtoul(buf, NULL, 10);
+	if (bit & ~1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
+	if (bit)
+		data->beep_mask |= (1 << bitnr);
+	else
+		data->beep_mask &= ~(1 << bitnr);
+	gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 1);
+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 2);
+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 3);
+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 4);
+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 5);
+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 6);
+
 static struct attribute *gl518_attributes[] = {
-	&dev_attr_in0_input.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in2_input.attr,
 	&dev_attr_in3_input.attr,
 	&dev_attr_in0_min.attr,
 	&dev_attr_in1_min.attr,
@@ -354,18 +420,32 @@
 	&dev_attr_in1_max.attr,
 	&dev_attr_in2_max.attr,
 	&dev_attr_in3_max.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in0_beep.dev_attr.attr,
+	&sensor_dev_attr_in1_beep.dev_attr.attr,
+	&sensor_dev_attr_in2_beep.dev_attr.attr,
+	&sensor_dev_attr_in3_beep.dev_attr.attr,
 
 	&dev_attr_fan1_auto.attr,
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_fan1_div.attr,
-	&dev_attr_fan2_div.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_beep.dev_attr.attr,
+	&sensor_dev_attr_fan2_beep.dev_attr.attr,
 
 	&dev_attr_temp1_input.attr,
 	&dev_attr_temp1_max.attr,
 	&dev_attr_temp1_max_hyst.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_beep.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
 	&dev_attr_beep_enable.attr,
@@ -377,6 +457,17 @@
 	.attrs = gl518_attributes,
 };
 
+static struct attribute *gl518_attributes_r80[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+	NULL
+};
+
+static const struct attribute_group gl518_group_r80 = {
+	.attrs = gl518_attributes_r80,
+};
+
 /*
  * Real code
  */
@@ -391,7 +482,7 @@
 static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct gl518_data *data;
 	int err = 0;
 
@@ -408,25 +499,24 @@
 		goto exit;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
+	client = &data->client;
+	i2c_set_clientdata(client, data);
 
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &gl518_driver;
-	new_client->flags = 0;
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &gl518_driver;
 
 	/* Now, we do the remaining detection. */
 
 	if (kind < 0) {
-		if ((gl518_read_value(new_client, GL518_REG_CHIP_ID) != 0x80)
-		 || (gl518_read_value(new_client, GL518_REG_CONF) & 0x80))
+		if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80)
+		 || (gl518_read_value(client, GL518_REG_CONF) & 0x80))
 			goto exit_free;
 	}
 
 	/* Determine the chip type. */
 	if (kind <= 0) {
-		i = gl518_read_value(new_client, GL518_REG_REVISION);
+		i = gl518_read_value(client, GL518_REG_REVISION);
 		if (i == 0x00) {
 			kind = gl518sm_r00;
 		} else if (i == 0x80) {
@@ -442,25 +532,27 @@
 	}
 
 	/* Fill in the remaining client fields */
-	strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE);
+	strlcpy(client->name, "gl518sm", I2C_NAME_SIZE);
 	data->type = kind;
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
 	/* Initialize the GL518SM chip */
 	data->alarm_mask = 0xff;
-	data->voltage_in[0]=data->voltage_in[1]=data->voltage_in[2]=0;
-	gl518_init_client((struct i2c_client *) new_client);
+	gl518_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &gl518_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group)))
 		goto exit_detach;
+	if (data->type == gl518sm_r80)
+		if ((err = sysfs_create_group(&client->dev.kobj,
+					      &gl518_group_r80)))
+			goto exit_remove_files;
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exit_remove_files;
@@ -469,9 +561,11 @@
 	return 0;
 
 exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &gl518_group);
+	sysfs_remove_group(&client->dev.kobj, &gl518_group);
+	if (data->type == gl518sm_r80)
+		sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
 exit_detach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 exit_free:
 	kfree(data);
 exit:
@@ -504,6 +598,8 @@
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &gl518_group);
+	if (data->type == gl518sm_r80)
+		sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
@@ -512,9 +608,9 @@
 	return 0;
 }
 
-/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
+/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
    GL518 uses a high-byte first convention, which is exactly opposite to
-   the usual practice. */
+   the SMBus standard. */
 static int gl518_read_value(struct i2c_client *client, u8 reg)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
@@ -523,9 +619,6 @@
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
-/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
-   GL518 uses a high-byte first convention, which is exactly opposite to
-   the usual practice. */
 static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 2d39d8f..03ecdc3 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -27,6 +27,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
@@ -43,9 +44,9 @@
 /* Insmod parameters */
 I2C_CLIENT_INSMOD_1(gl520sm);
 
-/* Many GL520 constants specified below 
+/* Many GL520 constants specified below
 One of the inputs can be configured as either temp or voltage.
-That's why _TEMP2 and _IN4 access the same register 
+That's why _TEMP2 and _IN4 access the same register
 */
 
 /* The GL520 registers */
@@ -56,37 +57,14 @@
 
 #define GL520_REG_VID_INPUT		0x02
 
-#define GL520_REG_IN0_INPUT		0x15
-#define GL520_REG_IN0_LIMIT		0x0c
-#define GL520_REG_IN0_MIN		GL520_REG_IN0_LIMIT
-#define GL520_REG_IN0_MAX		GL520_REG_IN0_LIMIT
+static const u8 GL520_REG_IN_INPUT[]	= { 0x15, 0x14, 0x13, 0x0d, 0x0e };
+static const u8 GL520_REG_IN_LIMIT[]	= { 0x0c, 0x09, 0x0a, 0x0b };
+static const u8 GL520_REG_IN_MIN[]	= { 0x0c, 0x09, 0x0a, 0x0b, 0x18 };
+static const u8 GL520_REG_IN_MAX[]	= { 0x0c, 0x09, 0x0a, 0x0b, 0x17 };
 
-#define GL520_REG_IN1_INPUT		0x14
-#define GL520_REG_IN1_LIMIT		0x09
-#define GL520_REG_IN1_MIN		GL520_REG_IN1_LIMIT
-#define GL520_REG_IN1_MAX		GL520_REG_IN1_LIMIT
-
-#define GL520_REG_IN2_INPUT		0x13
-#define GL520_REG_IN2_LIMIT		0x0a
-#define GL520_REG_IN2_MIN		GL520_REG_IN2_LIMIT
-#define GL520_REG_IN2_MAX		GL520_REG_IN2_LIMIT
-
-#define GL520_REG_IN3_INPUT		0x0d
-#define GL520_REG_IN3_LIMIT		0x0b
-#define GL520_REG_IN3_MIN		GL520_REG_IN3_LIMIT
-#define GL520_REG_IN3_MAX		GL520_REG_IN3_LIMIT
-
-#define GL520_REG_IN4_INPUT		0x0e
-#define GL520_REG_IN4_MAX		0x17
-#define GL520_REG_IN4_MIN		0x18
-
-#define GL520_REG_TEMP1_INPUT		0x04
-#define GL520_REG_TEMP1_MAX		0x05
-#define GL520_REG_TEMP1_MAX_HYST	0x06
-
-#define GL520_REG_TEMP2_INPUT		0x0e
-#define GL520_REG_TEMP2_MAX		0x17
-#define GL520_REG_TEMP2_MAX_HYST	0x18
+static const u8 GL520_REG_TEMP_INPUT[]		= { 0x04, 0x0e };
+static const u8 GL520_REG_TEMP_MAX[]		= { 0x05, 0x17 };
+static const u8 GL520_REG_TEMP_MAX_HYST[]	= { 0x06, 0x18 };
 
 #define GL520_REG_FAN_INPUT		0x07
 #define GL520_REG_FAN_MIN		0x08
@@ -114,7 +92,6 @@
 	.driver = {
 		.name	= "gl520sm",
 	},
-	.id		= I2C_DRIVERID_GL520,
 	.attach_adapter	= gl520_attach_adapter,
 	.detach_client	= gl520_detach_client,
 };
@@ -150,93 +127,13 @@
  * Sysfs stuff
  */
 
-#define sysfs_r(type, n, item, reg) \
-static ssize_t get_##type##item (struct gl520_data *, char *, int); \
-static ssize_t get_##type##n##item (struct device *, struct device_attribute *attr, char *); \
-static ssize_t get_##type##n##item (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct gl520_data *data = gl520_update_device(dev); \
-	return get_##type##item(data, buf, (n)); \
-}
-
-#define sysfs_w(type, n, item, reg) \
-static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \
-static ssize_t set_##type##n##item (struct device *, struct device_attribute *attr, const char *, size_t); \
-static ssize_t set_##type##n##item (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct gl520_data *data = i2c_get_clientdata(client); \
-	return set_##type##item(client, data, buf, count, (n), reg); \
-}
-
-#define sysfs_rw_n(type, n, item, reg) \
-sysfs_r(type, n, item, reg) \
-sysfs_w(type, n, item, reg) \
-static DEVICE_ATTR(type##n##item, S_IRUGO | S_IWUSR, get_##type##n##item, set_##type##n##item);
-
-#define sysfs_ro_n(type, n, item, reg) \
-sysfs_r(type, n, item, reg) \
-static DEVICE_ATTR(type##n##item, S_IRUGO, get_##type##n##item, NULL);
-
-#define sysfs_rw(type, item, reg) \
-sysfs_r(type, 0, item, reg) \
-sysfs_w(type, 0, item, reg) \
-static DEVICE_ATTR(type##item, S_IRUGO | S_IWUSR, get_##type##0##item, set_##type##0##item);
-
-#define sysfs_ro(type, item, reg) \
-sysfs_r(type, 0, item, reg) \
-static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL);
-
-
-#define sysfs_vid(n) \
-sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT)
-
-#define sysfs_in(n) \
-sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \
-sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \
-sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \
-
-#define sysfs_fan(n) \
-sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \
-sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \
-sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV)
-
-#define sysfs_fan_off(n) \
-sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \
-
-#define sysfs_temp(n) \
-sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \
-sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \
-sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST)
-
-#define sysfs_alarms() \
-sysfs_ro(alarms, , GL520_REG_ALARMS) \
-sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \
-sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK)
-
-
-sysfs_vid(0)
-
-sysfs_in(0)
-sysfs_in(1)
-sysfs_in(2)
-sysfs_in(3)
-sysfs_in(4)
-
-sysfs_fan(1)
-sysfs_fan(2)
-sysfs_fan_off(1)
-
-sysfs_temp(1)
-sysfs_temp(2)
-
-sysfs_alarms()
-
-
-static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n)
+static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
+	struct gl520_data *data = gl520_update_device(dev);
 	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
 }
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL);
 
 #define VDD_FROM_REG(val) (((val)*95+2)/4)
 #define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255))
@@ -244,8 +141,11 @@
 #define IN_FROM_REG(val) ((val)*19)
 #define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255))
 
-static ssize_t get_in_input(struct gl520_data *data, char *buf, int n)
+static ssize_t get_in_input(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
 	u8 r = data->in_input[n];
 
 	if (n == 0)
@@ -254,8 +154,11 @@
 		return sprintf(buf, "%d\n", IN_FROM_REG(r));
 }
 
-static ssize_t get_in_min(struct gl520_data *data, char *buf, int n)
+static ssize_t get_in_min(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
 	u8 r = data->in_min[n];
 
 	if (n == 0)
@@ -264,8 +167,11 @@
 		return sprintf(buf, "%d\n", IN_FROM_REG(r));
 }
 
-static ssize_t get_in_max(struct gl520_data *data, char *buf, int n)
+static ssize_t get_in_max(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
 	u8 r = data->in_max[n];
 
 	if (n == 0)
@@ -274,8 +180,12 @@
 		return sprintf(buf, "%d\n", IN_FROM_REG(r));
 }
 
-static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int n = to_sensor_dev_attr(attr)->index;
 	long v = simple_strtol(buf, NULL, 10);
 	u8 r;
 
@@ -289,16 +199,22 @@
 	data->in_min[n] = r;
 
 	if (n < 4)
-		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
+		gl520_write_value(client, GL520_REG_IN_MIN[n],
+				  (gl520_read_value(client, GL520_REG_IN_MIN[n])
+				   & ~0xff) | r);
 	else
-		gl520_write_value(client, reg, r);
+		gl520_write_value(client, GL520_REG_IN_MIN[n], r);
 
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int n = to_sensor_dev_attr(attr)->index;
 	long v = simple_strtol(buf, NULL, 10);
 	u8 r;
 
@@ -312,57 +228,109 @@
 	data->in_max[n] = r;
 
 	if (n < 4)
-		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
+		gl520_write_value(client, GL520_REG_IN_MAX[n],
+				  (gl520_read_value(client, GL520_REG_IN_MAX[n])
+				   & ~0xff00) | (r << 8));
 	else
-		gl520_write_value(client, reg, r);
+		gl520_write_value(client, GL520_REG_IN_MAX[n], r);
 
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, get_in_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_in_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_in_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, get_in_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, get_in_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
+		get_in_min, set_in_min, 0);
+static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
+		get_in_min, set_in_min, 1);
+static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
+		get_in_min, set_in_min, 2);
+static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
+		get_in_min, set_in_min, 3);
+static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
+		get_in_min, set_in_min, 4);
+static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
+		get_in_max, set_in_max, 0);
+static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
+		get_in_max, set_in_max, 1);
+static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
+		get_in_max, set_in_max, 2);
+static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
+		get_in_max, set_in_max, 3);
+static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
+		get_in_max, set_in_max, 4);
+
 #define DIV_FROM_REG(val) (1 << (val))
 #define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
 #define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255));
 
-static ssize_t get_fan_input(struct gl520_data *data, char *buf, int n)
+static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n - 1], data->fan_div[n - 1]));
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n],
+						 data->fan_div[n]));
 }
 
-static ssize_t get_fan_min(struct gl520_data *data, char *buf, int n)
+static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n - 1], data->fan_div[n - 1]));
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n],
+						 data->fan_div[n]));
 }
 
-static ssize_t get_fan_div(struct gl520_data *data, char *buf, int n)
+static ssize_t get_fan_div(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
-	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n - 1]));
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n]));
 }
 
-static ssize_t get_fan_off(struct gl520_data *data, char *buf, int n)
+static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
+	struct gl520_data *data = gl520_update_device(dev);
 	return sprintf(buf, "%d\n", data->fan_off);
 }
 
-static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int n = to_sensor_dev_attr(attr)->index;
 	unsigned long v = simple_strtoul(buf, NULL, 10);
 	u8 r;
 
 	mutex_lock(&data->update_lock);
-	r = FAN_TO_REG(v, data->fan_div[n - 1]);
-	data->fan_min[n - 1] = r;
+	r = FAN_TO_REG(v, data->fan_div[n]);
+	data->fan_min[n] = r;
 
-	if (n == 1)
-		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
+	if (n == 0)
+		gl520_write_value(client, GL520_REG_FAN_MIN,
+				  (gl520_read_value(client, GL520_REG_FAN_MIN)
+				   & ~0xff00) | (r << 8));
 	else
-		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
+		gl520_write_value(client, GL520_REG_FAN_MIN,
+				  (gl520_read_value(client, GL520_REG_FAN_MIN)
+				   & ~0xff) | r);
 
 	data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
-	if (data->fan_min[n - 1] == 0)
-		data->alarm_mask &= (n == 1) ? ~0x20 : ~0x40;
+	if (data->fan_min[n] == 0)
+		data->alarm_mask &= (n == 0) ? ~0x20 : ~0x40;
 	else
-		data->alarm_mask |= (n == 1) ? 0x20 : 0x40;
+		data->alarm_mask |= (n == 0) ? 0x20 : 0x40;
 	data->beep_mask &= data->alarm_mask;
 	gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
 
@@ -370,8 +338,12 @@
 	return count;
 }
 
-static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int n = to_sensor_dev_attr(attr)->index;
 	unsigned long v = simple_strtoul(buf, NULL, 10);
 	u8 r;
 
@@ -386,133 +358,282 @@
 	}
 
 	mutex_lock(&data->update_lock);
-	data->fan_div[n - 1] = r;
+	data->fan_div[n] = r;
 
-	if (n == 1)
-		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xc0) | (r << 6));
+	if (n == 0)
+		gl520_write_value(client, GL520_REG_FAN_DIV,
+				  (gl520_read_value(client, GL520_REG_FAN_DIV)
+				   & ~0xc0) | (r << 6));
 	else
-		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4));
+		gl520_write_value(client, GL520_REG_FAN_DIV,
+				  (gl520_read_value(client, GL520_REG_FAN_DIV)
+				   & ~0x30) | (r << 4));
 
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
 	u8 r = simple_strtoul(buf, NULL, 10)?1:0;
 
 	mutex_lock(&data->update_lock);
 	data->fan_off = r;
-	gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2));
+	gl520_write_value(client, GL520_REG_FAN_OFF,
+			  (gl520_read_value(client, GL520_REG_FAN_OFF)
+			   & ~0x0c) | (r << 2));
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
+		get_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
+		get_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+		get_fan_div, set_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
+		get_fan_div, set_fan_div, 1);
+static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR,
+		get_fan_off, set_fan_off);
+
 #define TEMP_FROM_REG(val) (((val) - 130) * 1000)
 #define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255))
 
-static ssize_t get_temp_input(struct gl520_data *data, char *buf, int n)
+static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n - 1]));
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n]));
 }
 
-static ssize_t get_temp_max(struct gl520_data *data, char *buf, int n)
+static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n - 1]));
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n]));
 }
 
-static ssize_t get_temp_max_hyst(struct gl520_data *data, char *buf, int n)
+static ssize_t get_temp_max_hyst(struct device *dev, struct device_attribute
+				 *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n - 1]));
+	int n = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n]));
 }
 
-static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int n = to_sensor_dev_attr(attr)->index;
 	long v = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
-	data->temp_max[n - 1] = TEMP_TO_REG(v);
-	gl520_write_value(client, reg, data->temp_max[n - 1]);
+	data->temp_max[n] = TEMP_TO_REG(v);
+	gl520_write_value(client, GL520_REG_TEMP_MAX[n], data->temp_max[n]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
+				 *attr, const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int n = to_sensor_dev_attr(attr)->index;
 	long v = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
-	data->temp_max_hyst[n - 1] = TEMP_TO_REG(v);
-	gl520_write_value(client, reg, data->temp_max_hyst[n - 1]);
+	data->temp_max_hyst[n] = TEMP_TO_REG(v);
+	gl520_write_value(client, GL520_REG_TEMP_MAX_HYST[n],
+			  data->temp_max_hyst[n]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t get_alarms(struct gl520_data *data, char *buf, int n)
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_temp_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
+		get_temp_max, set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
+		get_temp_max, set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
+		get_temp_max_hyst, set_temp_max_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
+		get_temp_max_hyst, set_temp_max_hyst, 1);
+
+static ssize_t get_alarms(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
+	struct gl520_data *data = gl520_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
 }
 
-static ssize_t get_beep_enable(struct gl520_data *data, char *buf, int n)
+static ssize_t get_beep_enable(struct device *dev, struct device_attribute
+			       *attr, char *buf)
 {
+	struct gl520_data *data = gl520_update_device(dev);
 	return sprintf(buf, "%d\n", data->beep_enable);
 }
 
-static ssize_t get_beep_mask(struct gl520_data *data, char *buf, int n)
+static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
+	struct gl520_data *data = gl520_update_device(dev);
 	return sprintf(buf, "%d\n", data->beep_mask);
 }
 
-static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_beep_enable(struct device *dev, struct device_attribute
+			       *attr, const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
 	u8 r = simple_strtoul(buf, NULL, 10)?0:1;
 
 	mutex_lock(&data->update_lock);
 	data->beep_enable = !r;
-	gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2));
+	gl520_write_value(client, GL520_REG_BEEP_ENABLE,
+			  (gl520_read_value(client, GL520_REG_BEEP_ENABLE)
+			   & ~0x04) | (r << 2));
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
 	u8 r = simple_strtoul(buf, NULL, 10);
-	
+
 	mutex_lock(&data->update_lock);
 	r &= data->alarm_mask;
 	data->beep_mask = r;
-	gl520_write_value(client, reg, r);
+	gl520_write_value(client, GL520_REG_BEEP_MASK, r);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
+static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
+static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+		get_beep_enable, set_beep_enable);
+static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
+		get_beep_mask, set_beep_mask);
+
+static ssize_t get_alarm(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	int bit_nr = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", (data->alarms >> bit_nr) & 1);
+}
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, get_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, get_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, get_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, get_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, get_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, get_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, get_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, get_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, get_alarm, NULL, 7);
+
+static ssize_t get_beep(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct gl520_data *data = gl520_update_device(dev);
+
+	return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1);
+}
+
+static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	unsigned long bit;
+
+	bit = simple_strtoul(buf, NULL, 10);
+	if (bit & ~1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+	if (bit)
+		data->beep_mask |= (1 << bitnr);
+	else
+		data->beep_mask &= ~(1 << bitnr);
+	gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 1);
+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 2);
+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 3);
+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 4);
+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 5);
+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 6);
+static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7);
+static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7);
+
 static struct attribute *gl520_attributes[] = {
 	&dev_attr_cpu0_vid.attr,
 
-	&dev_attr_in0_input.attr,
-	&dev_attr_in0_min.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in1_min.attr,
-	&dev_attr_in1_max.attr,
-	&dev_attr_in2_input.attr,
-	&dev_attr_in2_min.attr,
-	&dev_attr_in2_max.attr,
-	&dev_attr_in3_input.attr,
-	&dev_attr_in3_min.attr,
-	&dev_attr_in3_max.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in0_beep.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_beep.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_beep.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_beep.dev_attr.attr,
 
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_fan1_div.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_beep.dev_attr.attr,
 	&dev_attr_fan1_off.attr,
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_fan2_div.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_beep.dev_attr.attr,
 
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp1_max.attr,
-	&dev_attr_temp1_max_hyst.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_beep.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
 	&dev_attr_beep_enable.attr,
@@ -525,13 +646,17 @@
 };
 
 static struct attribute *gl520_attributes_opt[] = {
-	&dev_attr_in4_input.attr,
-	&dev_attr_in4_min.attr,
-	&dev_attr_in4_max.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_beep.dev_attr.attr,
 
-	&dev_attr_temp2_input.attr,
-	&dev_attr_temp2_max.attr,
-	&dev_attr_temp2_max_hyst.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_beep.dev_attr.attr,
 	NULL
 };
 
@@ -553,7 +678,7 @@
 
 static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct gl520_data *data;
 	int err = 0;
 
@@ -570,59 +695,65 @@
 		goto exit;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &gl520_driver;
-	new_client->flags = 0;
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &gl520_driver;
 
 	/* Determine the chip type. */
 	if (kind < 0) {
-		if ((gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) ||
-		    ((gl520_read_value(new_client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
-		    ((gl520_read_value(new_client, GL520_REG_CONF) & 0x80) != 0x00)) {
-			dev_dbg(&new_client->dev, "Unknown chip type, skipping\n");
+		if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) ||
+		    ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
+		    ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) {
+			dev_dbg(&client->dev, "Unknown chip type, skipping\n");
 			goto exit_free;
 		}
 	}
 
 	/* Fill in the remaining client fields */
-	strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE);
-	data->valid = 0;
+	strlcpy(client->name, "gl520sm", I2C_NAME_SIZE);
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
 	/* Initialize the GL520SM chip */
-	gl520_init_client(new_client);
+	gl520_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group)))
 		goto exit_detach;
 
 	if (data->two_temps) {
-		if ((err = device_create_file(&new_client->dev,
-					      &dev_attr_temp2_input))
-		 || (err = device_create_file(&new_client->dev,
-					      &dev_attr_temp2_max))
-		 || (err = device_create_file(&new_client->dev,
-					      &dev_attr_temp2_max_hyst)))
+		if ((err = device_create_file(&client->dev,
+				&sensor_dev_attr_temp2_input.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_temp2_max.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_temp2_max_hyst.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_temp2_alarm.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_temp2_beep.dev_attr)))
 			goto exit_remove_files;
 	} else {
-		if ((err = device_create_file(&new_client->dev,
-					      &dev_attr_in4_input))
-		 || (err = device_create_file(&new_client->dev,
-					      &dev_attr_in4_min))
-		 || (err = device_create_file(&new_client->dev,
-					      &dev_attr_in4_max)))
+		if ((err = device_create_file(&client->dev,
+				&sensor_dev_attr_in4_input.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_in4_min.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_in4_max.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_in4_alarm.dev_attr))
+		 || (err = device_create_file(&client->dev,
+				&sensor_dev_attr_in4_beep.dev_attr)))
 			goto exit_remove_files;
 	}
 
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto exit_remove_files;
@@ -631,10 +762,10 @@
 	return 0;
 
 exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &gl520_group);
-	sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt);
+	sysfs_remove_group(&client->dev.kobj, &gl520_group);
+	sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
 exit_detach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 exit_free:
 	kfree(data);
 exit:
@@ -697,7 +828,7 @@
 }
 
 
-/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
+/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
    GL520 uses a high-byte first convention */
 static int gl520_read_value(struct i2c_client *client, u8 reg)
 {
@@ -720,7 +851,7 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
-	int val;
+	int val, i;
 
 	mutex_lock(&data->update_lock);
 
@@ -732,18 +863,13 @@
 		data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
 		data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f;
 
-		val = gl520_read_value(client, GL520_REG_IN0_LIMIT);
-		data->in_min[0] = val & 0xff;
-		data->in_max[0] = (val >> 8) & 0xff;
-		val = gl520_read_value(client, GL520_REG_IN1_LIMIT);
-		data->in_min[1] = val & 0xff;
-		data->in_max[1] = (val >> 8) & 0xff;
-		val = gl520_read_value(client, GL520_REG_IN2_LIMIT);
-		data->in_min[2] = val & 0xff;
-		data->in_max[2] = (val >> 8) & 0xff;
-		val = gl520_read_value(client, GL520_REG_IN3_LIMIT);
-		data->in_min[3] = val & 0xff;
-		data->in_max[3] = (val >> 8) & 0xff;
+		for (i = 0; i < 4; i++) {
+			data->in_input[i] = gl520_read_value(client,
+							GL520_REG_IN_INPUT[i]);
+			val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]);
+			data->in_min[i] = val & 0xff;
+			data->in_max[i] = (val >> 8) & 0xff;
+		}
 
 		val = gl520_read_value(client, GL520_REG_FAN_INPUT);
 		data->fan_input[0] = (val >> 8) & 0xff;
@@ -753,9 +879,12 @@
 		data->fan_min[0] = (val >> 8) & 0xff;
 		data->fan_min[1] = val & 0xff;
 
-		data->temp_input[0] = gl520_read_value(client, GL520_REG_TEMP1_INPUT);
-		data->temp_max[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX);
-		data->temp_max_hyst[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX_HYST);
+		data->temp_input[0] = gl520_read_value(client,
+						GL520_REG_TEMP_INPUT[0]);
+		data->temp_max[0] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX[0]);
+		data->temp_max_hyst[0] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX_HYST[0]);
 
 		val = gl520_read_value(client, GL520_REG_FAN_DIV);
 		data->fan_div[0] = (val >> 6) & 0x03;
@@ -767,20 +896,21 @@
 		val = gl520_read_value(client, GL520_REG_CONF);
 		data->beep_enable = !((val >> 2) & 1);
 
-		data->in_input[0] = gl520_read_value(client, GL520_REG_IN0_INPUT);
-		data->in_input[1] = gl520_read_value(client, GL520_REG_IN1_INPUT);
-		data->in_input[2] = gl520_read_value(client, GL520_REG_IN2_INPUT);
-		data->in_input[3] = gl520_read_value(client, GL520_REG_IN3_INPUT);
-
 		/* Temp1 and Vin4 are the same input */
 		if (data->two_temps) {
-			data->temp_input[1] = gl520_read_value(client, GL520_REG_TEMP2_INPUT);
-			data->temp_max[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX);
-			data->temp_max_hyst[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX_HYST);
+			data->temp_input[1] = gl520_read_value(client,
+						GL520_REG_TEMP_INPUT[1]);
+			data->temp_max[1] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX[1]);
+			data->temp_max_hyst[1] = gl520_read_value(client,
+						GL520_REG_TEMP_MAX_HYST[1]);
 		} else {
-			data->in_input[4] = gl520_read_value(client, GL520_REG_IN4_INPUT);
-			data->in_min[4] = gl520_read_value(client, GL520_REG_IN4_MIN);
-			data->in_max[4] = gl520_read_value(client, GL520_REG_IN4_MAX);
+			data->in_input[4] = gl520_read_value(client,
+						GL520_REG_IN_INPUT[4]);
+			data->in_min[4] = gl520_read_value(client,
+						GL520_REG_IN_MIN[4]);
+			data->in_max[4] = gl520_read_value(client,
+						GL520_REG_IN_MAX[4]);
 		}
 
 		data->last_updated = jiffies;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index ad6c8a3..e12c132 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -17,8 +17,8 @@
               IT8726F  Super I/O chip w/LPC interface
               Sis950   A clone of the IT8705F
 
-    Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> 
-    Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2001 Chris Gauthron
+    Copyright (C) 2005-2007 Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -52,6 +52,10 @@
 
 enum chips { it87, it8712, it8716, it8718 };
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define	REG	0x2e	/* The register to read/write */
@@ -776,6 +780,30 @@
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
+
 static ssize_t
 show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -837,6 +865,14 @@
 	&sensor_dev_attr_in5_max.dev_attr.attr,
 	&sensor_dev_attr_in6_max.dev_attr.attr,
 	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
+	&sensor_dev_attr_in6_alarm.dev_attr.attr,
+	&sensor_dev_attr_in7_alarm.dev_attr.attr,
 
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp2_input.dev_attr.attr,
@@ -850,6 +886,9 @@
 	&sensor_dev_attr_temp1_type.dev_attr.attr,
 	&sensor_dev_attr_temp2_type.dev_attr.attr,
 	&sensor_dev_attr_temp3_type.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
 	&dev_attr_name.attr,
@@ -882,12 +921,21 @@
 	&sensor_dev_attr_fan3_min.dev_attr.attr,
 	&sensor_dev_attr_fan3_div.dev_attr.attr,
 
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
+
 	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm1.dev_attr.attr,
 	&sensor_dev_attr_pwm2.dev_attr.attr,
 	&sensor_dev_attr_pwm3.dev_attr.attr,
+	&dev_attr_pwm1_freq.attr,
+	&dev_attr_pwm2_freq.attr,
+	&dev_attr_pwm3_freq.attr,
 
 	&dev_attr_vrm.attr,
 	&dev_attr_cpu0_vid.attr,
@@ -906,7 +954,7 @@
 	u16 chip_type;
 
 	superio_enter();
-	chip_type = superio_inw(DEVID);
+	chip_type = force_id ? force_id : superio_inw(DEVID);
 
 	switch (chip_type) {
 	case IT8705F_DEVID:
@@ -1027,35 +1075,45 @@
 			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_input16.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_min16.dev_attr)))
+			     &sensor_dev_attr_fan1_min16.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan1_alarm.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 1)) {
 			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_input16.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_min16.dev_attr)))
+			     &sensor_dev_attr_fan2_min16.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan2_alarm.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 2)) {
 			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_input16.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_min16.dev_attr)))
+			     &sensor_dev_attr_fan3_min16.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan3_alarm.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 3)) {
 			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan4_input16.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan4_min16.dev_attr)))
+			     &sensor_dev_attr_fan4_min16.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan4_alarm.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 4)) {
 			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan5_input16.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan5_min16.dev_attr)))
+			     &sensor_dev_attr_fan5_min16.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan5_alarm.dev_attr)))
 				goto ERROR4;
 		}
 	} else {
@@ -1066,7 +1124,9 @@
 			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_min.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_div.dev_attr)))
+			     &sensor_dev_attr_fan1_div.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan1_alarm.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 1)) {
@@ -1075,7 +1135,9 @@
 			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_min.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_div.dev_attr)))
+			     &sensor_dev_attr_fan2_div.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan2_alarm.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 2)) {
@@ -1084,7 +1146,9 @@
 			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_min.dev_attr))
 			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_div.dev_attr)))
+			     &sensor_dev_attr_fan3_div.dev_attr))
+			 || (err = device_create_file(dev,
+			     &sensor_dev_attr_fan3_alarm.dev_attr)))
 				goto ERROR4;
 		}
 	}
@@ -1488,7 +1552,7 @@
 }
 
 
-MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>, "
+MODULE_AUTHOR("Chris Gauthron, "
 	      "Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8726F, SiS950 driver");
 module_param(update_vbat, bool, 0);
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 37a8cc0..e5c35a3 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -74,7 +74,6 @@
 	.driver = {
 		.name	= "lm75",
 	},
-	.id		= I2C_DRIVERID_LM75,
 	.attach_adapter	= lm75_attach_adapter,
 	.detach_client	= lm75_detach_client,
 };
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index cee5c2e..459b70a 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -31,6 +31,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 
@@ -113,7 +114,6 @@
 show(temp_crit);
 show(temp_min);
 show(temp_max);
-show(alarms);
 
 /* read routines for hysteresis values */
 static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
@@ -186,6 +186,14 @@
 	return count;
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct lm77_data *data = lm77_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+
 static DEVICE_ATTR(temp1_input, S_IRUGO,
 		   show_temp_input, NULL);
 static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
@@ -202,8 +210,9 @@
 static DEVICE_ATTR(temp1_max_hyst, S_IRUGO,
 		   show_temp_max_hyst, NULL);
 
-static DEVICE_ATTR(alarms, S_IRUGO,
-		   show_alarms, NULL);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1);
 
 static int lm77_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -220,8 +229,9 @@
 	&dev_attr_temp1_crit_hyst.attr,
 	&dev_attr_temp1_min_hyst.attr,
 	&dev_attr_temp1_max_hyst.attr,
-	&dev_attr_alarms.attr,
-
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
 	NULL
 };
 
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 3f7055e..0a9eb1f 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -37,10 +37,8 @@
 static struct platform_device *pdev;
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
-					0x25, 0x26, 0x27, 0x28, 0x29,
-					0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
-					0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
+				       0x2e, 0x2f, I2C_CLIENT_END };
 static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
@@ -170,7 +168,6 @@
 	.driver = {
 		.name	= "lm78",
 	},
-	.id		= I2C_DRIVERID_LM78,
 	.attach_adapter	= lm78_attach_adapter,
 	.detach_client	= lm78_detach_client,
 };
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 063cdba..a2ca055 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -27,6 +27,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 
@@ -127,7 +128,7 @@
 	u16 alarms;		/* Register encoding, combined */
 };
 
-/* 
+/*
  * Functions declaration
  */
 
@@ -147,7 +148,6 @@
 	.driver = {
 		.name	= "lm80",
 	},
-	.id		= I2C_DRIVERID_LM80,
 	.attach_adapter	= lm80_attach_adapter,
 	.detach_client	= lm80_detach_client,
 };
@@ -159,105 +159,74 @@
 #define show_in(suffix, value) \
 static ssize_t show_in_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct lm80_data *data = lm80_update_device(dev); \
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->value)); \
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \
 }
-show_in(min0, in_min[0]);
-show_in(min1, in_min[1]);
-show_in(min2, in_min[2]);
-show_in(min3, in_min[3]);
-show_in(min4, in_min[4]);
-show_in(min5, in_min[5]);
-show_in(min6, in_min[6]);
-show_in(max0, in_max[0]);
-show_in(max1, in_max[1]);
-show_in(max2, in_max[2]);
-show_in(max3, in_max[3]);
-show_in(max4, in_max[4]);
-show_in(max5, in_max[5]);
-show_in(max6, in_max[6]);
-show_in(input0, in[0]);
-show_in(input1, in[1]);
-show_in(input2, in[2]);
-show_in(input3, in[3]);
-show_in(input4, in[4]);
-show_in(input5, in[5]);
-show_in(input6, in[6]);
+show_in(min, in_min)
+show_in(max, in_max)
+show_in(input, in)
 
 #define set_in(suffix, value, reg) \
 static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct lm80_data *data = i2c_get_clientdata(client); \
 	long val = simple_strtol(buf, NULL, 10); \
  \
 	mutex_lock(&data->update_lock);\
-	data->value = IN_TO_REG(val); \
-	lm80_write_value(client, reg, data->value); \
+	data->value[nr] = IN_TO_REG(val); \
+	lm80_write_value(client, reg(nr), data->value[nr]); \
 	mutex_unlock(&data->update_lock);\
 	return count; \
 }
-set_in(min0, in_min[0], LM80_REG_IN_MIN(0));
-set_in(min1, in_min[1], LM80_REG_IN_MIN(1));
-set_in(min2, in_min[2], LM80_REG_IN_MIN(2));
-set_in(min3, in_min[3], LM80_REG_IN_MIN(3));
-set_in(min4, in_min[4], LM80_REG_IN_MIN(4));
-set_in(min5, in_min[5], LM80_REG_IN_MIN(5));
-set_in(min6, in_min[6], LM80_REG_IN_MIN(6));
-set_in(max0, in_max[0], LM80_REG_IN_MAX(0));
-set_in(max1, in_max[1], LM80_REG_IN_MAX(1));
-set_in(max2, in_max[2], LM80_REG_IN_MAX(2));
-set_in(max3, in_max[3], LM80_REG_IN_MAX(3));
-set_in(max4, in_max[4], LM80_REG_IN_MAX(4));
-set_in(max5, in_max[5], LM80_REG_IN_MAX(5));
-set_in(max6, in_max[6], LM80_REG_IN_MAX(6));
+set_in(min, in_min, LM80_REG_IN_MIN)
+set_in(max, in_max, LM80_REG_IN_MAX)
 
-#define show_fan(suffix, value, div) \
+#define show_fan(suffix, value) \
 static ssize_t show_fan_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
+	int nr = to_sensor_dev_attr(attr)->index; \
 	struct lm80_data *data = lm80_update_device(dev); \
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value, \
-		       DIV_FROM_REG(data->div))); \
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \
+		       DIV_FROM_REG(data->fan_div[nr]))); \
 }
-show_fan(min1, fan_min[0], fan_div[0]);
-show_fan(min2, fan_min[1], fan_div[1]);
-show_fan(input1, fan[0], fan_div[0]);
-show_fan(input2, fan[1], fan_div[1]);
+show_fan(min, fan_min)
+show_fan(input, fan)
 
-#define show_fan_div(suffix, value) \
-static ssize_t show_fan_div##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct lm80_data *data = lm80_update_device(dev); \
-	return sprintf(buf, "%d\n", DIV_FROM_REG(data->value)); \
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+	char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct lm80_data *data = lm80_update_device(dev);
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
-show_fan_div(1, fan_div[0]);
-show_fan_div(2, fan_div[1]);
 
-#define set_fan(suffix, value, reg, div) \
-static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm80_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtoul(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock);\
-	data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \
-	lm80_write_value(client, reg, data->value); \
-	mutex_unlock(&data->update_lock);\
-	return count; \
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm80_data *data = i2c_get_clientdata(client);
+	long val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+	lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
 }
-set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]);
-set_fan(min2, fan_min[1], LM80_REG_FAN_MIN(2), fan_div[1]);
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
    least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-	size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t count)
 {
+	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm80_data *data = i2c_get_clientdata(client);
 	unsigned long min, val = simple_strtoul(buf, NULL, 10);
@@ -292,15 +261,6 @@
 	return count;
 }
 
-#define set_fan_div(number) \
-static ssize_t set_fan_div##number(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	return set_fan_div(dev, buf, count, number - 1); \
-}
-set_fan_div(1);
-set_fan_div(2);
-
 static ssize_t show_temp_input1(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
@@ -337,41 +297,66 @@
 set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX);
 set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
 }
 
-static DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0);
-static DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min1, set_in_min1);
-static DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min2, set_in_min2);
-static DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min3, set_in_min3);
-static DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min4, set_in_min4);
-static DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min5, set_in_min5);
-static DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min6, set_in_min6);
-static DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max0, set_in_max0);
-static DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max1, set_in_max1);
-static DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max2, set_in_max2);
-static DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max3, set_in_max3);
-static DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max4, set_in_max4);
-static DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max5, set_in_max5);
-static DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max6, set_in_max6);
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);
-static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);
-static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);
-static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL);
-static DEVICE_ATTR(in4_input, S_IRUGO, show_in_input4, NULL);
-static DEVICE_ATTR(in5_input, S_IRUGO, show_in_input5, NULL);
-static DEVICE_ATTR(in6_input, S_IRUGO, show_in_input6, NULL);
-static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min1,
-    set_fan_min1);
-static DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min2,
-    set_fan_min2);
-static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL);
-static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL);
-static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div1, set_fan_div1);
-static DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div2, set_fan_div2);
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct lm80_data *data = lm80_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+
+static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 0);
+static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 1);
+static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 2);
+static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 3);
+static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 4);
+static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 5);
+static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO,
+		show_in_min, set_in_min, 6);
+static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 0);
+static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 1);
+static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 2);
+static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 3);
+static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 4);
+static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 5);
+static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO,
+		show_in_max, set_in_max, 6);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+		show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+		show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO,
+		show_fan_div, set_fan_div, 0);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO,
+		show_fan_div, set_fan_div, 1);
 static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
 static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max,
     set_temp_hot_max);
@@ -382,6 +367,17 @@
 static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst,
     set_temp_os_hyst);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
 
 /*
  * Real code
@@ -395,40 +391,50 @@
 }
 
 static struct attribute *lm80_attributes[] = {
-	&dev_attr_in0_min.attr,
-	&dev_attr_in1_min.attr,
-	&dev_attr_in2_min.attr,
-	&dev_attr_in3_min.attr,
-	&dev_attr_in4_min.attr,
-	&dev_attr_in5_min.attr,
-	&dev_attr_in6_min.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in1_max.attr,
-	&dev_attr_in2_max.attr,
-	&dev_attr_in3_max.attr,
-	&dev_attr_in4_max.attr,
-	&dev_attr_in5_max.attr,
-	&dev_attr_in6_max.attr,
-	&dev_attr_in0_input.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in2_input.attr,
-	&dev_attr_in3_input.attr,
-	&dev_attr_in4_input.attr,
-	&dev_attr_in5_input.attr,
-	&dev_attr_in6_input.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan1_div.attr,
-	&dev_attr_fan2_div.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
 	&dev_attr_temp1_input.attr,
 	&dev_attr_temp1_max.attr,
 	&dev_attr_temp1_max_hyst.attr,
 	&dev_attr_temp1_crit.attr,
 	&dev_attr_temp1_crit_hyst.attr,
 	&dev_attr_alarms.attr,
-
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
+	&sensor_dev_attr_in6_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
 	NULL
 };
 
@@ -439,7 +445,7 @@
 static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i, cur;
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct lm80_data *data;
 	int err = 0;
 	const char *name;
@@ -455,21 +461,20 @@
 		goto exit;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &lm80_driver;
-	new_client->flags = 0;
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &lm80_driver;
 
 	/* Now, we do the remaining detection. It is lousy. */
-	if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)
+	if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
 		goto error_free;
 	for (i = 0x2a; i <= 0x3d; i++) {
-		cur = i2c_smbus_read_byte_data(new_client, i);
-		if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur)
-		 || (i2c_smbus_read_byte_data(new_client, i + 0x80) != cur)
-		 || (i2c_smbus_read_byte_data(new_client, i + 0xc0) != cur))
+		cur = i2c_smbus_read_byte_data(client, i);
+		if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
+		 || (i2c_smbus_read_byte_data(client, i + 0x80) != cur)
+		 || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur))
 		    goto error_free;
 	}
 
@@ -477,27 +482,26 @@
 	kind = lm80;
 	name = "lm80";
 
-	/* Fill in the remaining client fields and put it into the global list */
-	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	data->valid = 0;
+	/* Fill in the remaining client fields */
+	strlcpy(client->name, name, I2C_NAME_SIZE);
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto error_free;
 
 	/* Initialize the LM80 chip */
-	lm80_init_client(new_client);
+	lm80_init_client(client);
 
 	/* A few vars need to be filled upon startup */
-	data->fan_min[0] = lm80_read_value(new_client, LM80_REG_FAN_MIN(1));
-	data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
+	data->fan_min[0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
+	data->fan_min[1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm80_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group)))
 		goto error_detach;
 
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
 		goto error_remove;
@@ -506,9 +510,9 @@
 	return 0;
 
 error_remove:
-	sysfs_remove_group(&new_client->dev.kobj, &lm80_group);
+	sysfs_remove_group(&client->dev.kobj, &lm80_group);
 error_detach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 error_free:
 	kfree(data);
 exit:
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 0336b45..6e8903a6e 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -133,7 +133,6 @@
 	.driver = {
 		.name	= "lm83",
 	},
-	.id		= I2C_DRIVERID_LM83,
 	.attach_adapter	= lm83_attach_adapter,
 	.detach_client	= lm83_detach_client,
 };
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index a02480b..4bb0f29 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -367,7 +367,6 @@
 	.driver = {
 		.name   = "lm85",
 	},
-	.id             = I2C_DRIVERID_LM85,
 	.attach_adapter = lm85_attach_adapter,
 	.detach_client  = lm85_detach_client,
 };
@@ -444,12 +443,8 @@
 
 static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm85_data *data = i2c_get_clientdata(client);
-	u32 val;
-
-	val = simple_strtoul(buf, NULL, 10);
-	data->vrm = val;
+	struct lm85_data *data = dev_get_drvdata(dev);
+	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
 
@@ -519,17 +514,64 @@
 {
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct lm85_data *data = lm85_update_device(dev);
-	int	pwm_zone;
+	int pwm_zone, enable;
 
 	pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
-	return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+	switch (pwm_zone) {
+	case -1:	/* PWM is always at 100% */
+		enable = 0;
+		break;
+	case 0:		/* PWM is always at 0% */
+	case -2:	/* PWM responds to manual control */
+		enable = 1;
+		break;
+	default:	/* PWM in automatic mode */
+		enable = 2;
+	}
+	return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+		*attr, const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	u8 config;
+
+	switch (val) {
+	case 0:
+		config = 3;
+		break;
+	case 1:
+		config = 7;
+		break;
+	case 2:
+		/* Here we have to choose arbitrarily one of the 5 possible
+		   configurations; I go for the safest */
+		config = 6;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->autofan[nr].config = lm85_read_value(client,
+		LM85_REG_AFAN_CONFIG(nr));
+	data->autofan[nr].config = (data->autofan[nr].config & ~0xe0)
+		| (config << 5);
+	lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr),
+		data->autofan[nr].config);
+	mutex_unlock(&data->update_lock);
+	return count;
 }
 
 #define show_pwm_reg(offset)						\
 static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,		\
 		show_pwm, set_pwm, offset - 1);				\
-static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO,		\
-		show_pwm_enable, NULL, offset - 1)
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,	\
+		show_pwm_enable, set_pwm_enable, offset - 1)
 
 show_pwm_reg(1);
 show_pwm_reg(2);
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 28cdff0..8ee07c5 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -5,7 +5,7 @@
  *                          Philip Edelbrock <phil@netroedge.com>
  *                          Stephen Rousset <stephen.rousset@rocketlogix.com>
  *                          Dan Eaton <dan.eaton@rocketlogix.com>
- * Copyright (C) 2004       Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004,2007  Jean Delvare <khali@linux-fr.org>
  *
  * Original port to Linux 2.6 by Jeff Oliver.
  *
@@ -37,6 +37,11 @@
  * instead. The LM87 is the only hardware monitoring chipset I know of
  * which uses amplitude modulation. Be careful when using this feature.
  *
+ * This driver also supports the ADM1024, a sensor chip made by Analog
+ * Devices. That chip is fully compatible with the LM87. Complete
+ * datasheet can be obtained from Analog's website at:
+ *   http://www.analog.com/en/prod/0,2877,ADM1024,00.html
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -74,7 +79,7 @@
  * Insmod parameters
  */
 
-I2C_CLIENT_INSMOD_1(lm87);
+I2C_CLIENT_INSMOD_2(lm87, adm1024);
 
 /*
  * The LM87 registers
@@ -166,7 +171,6 @@
 	.driver = {
 		.name	= "lm87",
 	},
-	.id		= I2C_DRIVERID_LM87,
 	.attach_adapter	= lm87_attach_adapter,
 	.detach_client	= lm87_detach_client,
 };
@@ -506,8 +510,7 @@
 }
 static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm87_data *data = i2c_get_clientdata(client);
+	struct lm87_data *data = dev_get_drvdata(dev);
 	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
@@ -662,6 +665,7 @@
 	struct i2c_client *new_client;
 	struct lm87_data *data;
 	int err = 0;
+	static const char *names[] = { "lm87", "adm1024" };
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
@@ -686,11 +690,18 @@
 
 	/* Now, we do the remaining detection. */
 	if (kind < 0) {
+		u8 cid = lm87_read_value(new_client, LM87_REG_COMPANY_ID);
 		u8 rev = lm87_read_value(new_client, LM87_REG_REVISION);
 
-		if (rev < 0x01 || rev > 0x08
-		 || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)
-		 || lm87_read_value(new_client, LM87_REG_COMPANY_ID) != 0x02) {
+		if (cid == 0x02			/* National Semiconductor */
+		 && (rev >= 0x01 && rev <= 0x08))
+			kind = lm87;
+		else if (cid == 0x41		/* Analog Devices */
+		      && (rev & 0xf0) == 0x10)
+			kind = adm1024;
+
+		if (kind < 0
+		 || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) {
 			dev_dbg(&adapter->dev,
 				"LM87 detection failed at 0x%02x.\n",
 				address);
@@ -699,7 +710,7 @@
 	}
 
 	/* We can fill in the remaining client fields */
-	strlcpy(new_client->name, "lm87", I2C_NAME_SIZE);
+	strlcpy(new_client->name, names[kind - 1], I2C_NAME_SIZE);
 	data->valid = 0;
 	mutex_init(&data->update_lock);
 
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 960df9f..f7ec95b 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -204,7 +204,6 @@
 	.driver = {
 		.name	= "lm90",
 	},
-	.id		= I2C_DRIVERID_LM90,
 	.attach_adapter	= lm90_attach_adapter,
 	.detach_client	= lm90_detach_client,
 };
@@ -531,24 +530,24 @@
 		kind = lm90;
 
 	if (kind < 0) { /* detection and identification */
-		u8 man_id, chip_id, reg_config1, reg_convrate;
+		int man_id, chip_id, reg_config1, reg_convrate;
 
-		if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID,
-				  &man_id) < 0
-		 || lm90_read_reg(new_client, LM90_REG_R_CHIP_ID,
-		 		  &chip_id) < 0
-		 || lm90_read_reg(new_client, LM90_REG_R_CONFIG1,
-		 		  &reg_config1) < 0
-		 || lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
-		 		  &reg_convrate) < 0)
+		if ((man_id = i2c_smbus_read_byte_data(new_client,
+						LM90_REG_R_MAN_ID)) < 0
+		 || (chip_id = i2c_smbus_read_byte_data(new_client,
+						LM90_REG_R_CHIP_ID)) < 0
+		 || (reg_config1 = i2c_smbus_read_byte_data(new_client,
+						LM90_REG_R_CONFIG1)) < 0
+		 || (reg_convrate = i2c_smbus_read_byte_data(new_client,
+						LM90_REG_R_CONVRATE)) < 0)
 			goto exit_free;
 		
 		if ((address == 0x4C || address == 0x4D)
 		 && man_id == 0x01) { /* National Semiconductor */
-			u8 reg_config2;
+			int reg_config2;
 
-			if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
-					  &reg_config2) < 0)
+			if ((reg_config2 = i2c_smbus_read_byte_data(new_client,
+						LM90_REG_R_CONFIG2)) < 0)
 				goto exit_free;
 
 			if ((reg_config1 & 0x2A) == 0x00
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 61d1bd1..af5c77d 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -428,7 +428,6 @@
 	.driver = {
 		.name	= "lm92",
 	},
-	.id		= I2C_DRIVERID_LM92,
 	.attach_adapter	= lm92_attach_adapter,
 	.detach_client	= lm92_detach_client,
 };
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 9d66013..9b462bb 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -59,6 +59,10 @@
  " 2: Forcibly enable all voltage and temperature channels, except in9\n"
  " 3: Forcibly enable all voltage and temperature channels, including in9");
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 /*
  * Super-I/O registers and operations
  */
@@ -826,7 +830,7 @@
 	/* No superio_enter */
 
 	/* Identify device */
-	val = superio_inb(sioaddr, DEVID);
+	val = force_id ? force_id : superio_inb(sioaddr, DEVID);
 	switch (val) {
 	case 0xE1: /* PC87360 */
 	case 0xE8: /* PC87363 */
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index d40509a..7265f22 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -34,6 +34,10 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define DRVNAME "pc87427"
@@ -555,7 +559,7 @@
 	int i, err = 0;
 
 	/* Identify device */
-	val = superio_inb(sioaddr, SIOREG_DEVID);
+	val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID);
 	if (val != 0xf2) {	/* PC87427 */
 		err = -ENODEV;
 		goto exit;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 0b57d2e..f61d8f4 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -38,6 +38,10 @@
 #include <linux/mutex.h>
 #include <asm/io.h>
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define DRVNAME "smsc47b397"
@@ -333,7 +337,7 @@
 	u8 id, rev;
 
 	superio_enter();
-	id = superio_inb(SUPERIO_REG_DEVID);
+	id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
 	if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) {
 		superio_exit();
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index a10a380..0d7f0c4 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -39,6 +39,10 @@
 #include <linux/sysfs.h>
 #include <asm/io.h>
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define DRVNAME "smsc47m1"
@@ -399,7 +403,7 @@
 	u8 val;
 
 	superio_enter();
-	val = superio_inb(SUPERIO_REG_DEVID);
+	val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
 	/*
 	 * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index b875526..8b0c188 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -341,8 +341,7 @@
 static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	struct smsc47m192_data *data = dev_get_drvdata(dev);
 	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 7dfcc8d..12b4359 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -42,6 +42,10 @@
 module_param(int_mode, int, 0);
 MODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode");
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define DRVNAME "vt1211"
@@ -1280,10 +1284,12 @@
 static int __init vt1211_find(int sio_cip, unsigned short *address)
 {
 	int err = -ENODEV;
+	int devid;
 
 	superio_enter(sio_cip);
 
-	if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) {
+	devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID);
+	if (devid != SIO_VT1211_ID) {
 		goto EXIT;
 	}
 
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 2196a84..f876617 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -504,7 +504,7 @@
 	case 4: data->fan_div[nr] = 2; break;
 	case 8: data->fan_div[nr] = 3; break;
 	default:
-		dev_err(dev, "fan_div value %ld not supported."
+		dev_err(dev, "fan_div value %ld not supported. "
 		        "Choose one of 1, 2, 4 or 8!\n", val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index d5aa25c..075164d 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -59,6 +59,10 @@
 	"w83627dhg",
 };
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 #define DRVNAME "w83627ehf"
 
 /*
@@ -1198,8 +1202,7 @@
 		device_remove_file(dev, &sda_temp[i].dev_attr);
 
 	device_remove_file(dev, &dev_attr_name);
-	if (data->vid != 0x3f)
-		device_remove_file(dev, &dev_attr_cpu0_vid);
+	device_remove_file(dev, &dev_attr_cpu0_vid);
 }
 
 /* Get the monitoring functions started */
@@ -1299,11 +1302,16 @@
 			}
 		}
 
-		data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f;
+		data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA);
+		if (sio_data->kind == w83627ehf) /* 6 VID pins only */
+			data->vid &= 0x3f;
+
+		err = device_create_file(dev, &dev_attr_cpu0_vid);
+		if (err)
+			goto exit_release;
 	} else {
 		dev_info(dev, "VID pins in output mode, CPU VID not "
 			 "available\n");
-		data->vid = 0x3f;
 	}
 
 	/* fan4 and fan5 share some pins with the GPIO and serial flash */
@@ -1386,12 +1394,6 @@
 	if (err)
 		goto exit_remove;
 
-	if (data->vid != 0x3f) {
-		err = device_create_file(dev, &dev_attr_cpu0_vid);
-		if (err)
-			goto exit_remove;
-	}
-
 	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
@@ -1445,8 +1447,11 @@
 
 	superio_enter(sioaddr);
 
-	val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
-	    | superio_inb(sioaddr, SIO_REG_DEVID + 1);
+	if (force_id)
+		val = force_id;
+	else
+		val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
+		    | superio_inb(sioaddr, SIO_REG_DEVID + 1);
 	switch (val & SIO_ID_MASK) {
 	case SIO_W83627EHF_ID:
 		sio_data->kind = w83627ehf;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 879d0a6..9564fb0 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -75,6 +75,10 @@
 module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 /* modified from kernel/include/traps.c */
 static int REG;		/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
@@ -319,10 +323,8 @@
 		return (0x80 | (180000UL / (val << 8)));
 }
 
-#define BEEP_MASK_FROM_REG(val)		 (val)
-#define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
-#define BEEP_ENABLE_TO_REG(val)		((val)?1:0)
-#define BEEP_ENABLE_FROM_REG(val)	((val)?1:0)
+#define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
+#define BEEP_MASK_TO_REG(val)		((val) & 0xff7fff)
 
 #define DIV_FROM_REG(val) (1 << (val))
 
@@ -363,7 +365,6 @@
 	u8 vid;			/* Register encoding, combined */
 	u32 alarms;		/* Register encoding, combined */
 	u32 beep_mask;		/* Register encoding, combined */
-	u8 beep_enable;		/* Boolean */
 	u8 pwm[3];		/* Register value */
 	u8 pwm_freq[3];		/* Register value */
 	u16 sens[3];		/* 1 = pentium diode; 2 = 3904 diode;
@@ -713,65 +714,151 @@
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 
-#define show_beep_reg(REG, reg) \
-static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct w83627hf_data *data = w83627hf_update_device(dev); \
-	return sprintf(buf,"%ld\n", \
-		      (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
+static ssize_t
+show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
 }
-show_beep_reg(ENABLE, enable)
-show_beep_reg(MASK, mask)
-
-#define BEEP_ENABLE			0	/* Store beep_enable */
-#define BEEP_MASK			1	/* Store beep_mask */
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
 
 static ssize_t
-store_beep_reg(struct device *dev, const char *buf, size_t count,
-	       int update_mask)
+show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	return sprintf(buf, "%ld\n",
+		      (long)BEEP_MASK_FROM_REG(data->beep_mask));
+}
+
+static ssize_t
+store_beep_mask(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val, val2;
+	unsigned long val;
 
 	val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 
-	if (update_mask == BEEP_MASK) {	/* We are storing beep_mask */
-		data->beep_mask = BEEP_MASK_TO_REG(val);
-		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
-				    data->beep_mask & 0xff);
-		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
-				    ((data->beep_mask) >> 16) & 0xff);
-		val2 = (data->beep_mask >> 8) & 0x7f;
-	} else {		/* We are storing beep_enable */
-		val2 =
-		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
-		data->beep_enable = BEEP_ENABLE_TO_REG(val);
-	}
-
+	/* preserve beep enable */
+	data->beep_mask = (data->beep_mask & 0x8000)
+			| BEEP_MASK_TO_REG(val);
+	w83627hf_write_value(data, W83781D_REG_BEEP_INTS1,
+			    data->beep_mask & 0xff);
+	w83627hf_write_value(data, W83781D_REG_BEEP_INTS3,
+			    ((data->beep_mask) >> 16) & 0xff);
 	w83627hf_write_value(data, W83781D_REG_BEEP_INTS2,
-			    val2 | data->beep_enable << 7);
+			    (data->beep_mask >> 8) & 0xff);
 
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-#define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	return show_beep_##reg(dev, attr, buf); \
-} \
-static ssize_t \
-store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-	return store_beep_reg(dev, buf, count, BEEP_##REG); \
-} \
-static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \
-		  show_regs_beep_##reg, store_regs_beep_##reg);
+static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
+		   show_beep_mask, store_beep_mask);
 
-sysfs_beep(ENABLE, enable);
-sysfs_beep(MASK, mask);
+static ssize_t
+show_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct w83627hf_data *data = dev_get_drvdata(dev);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	unsigned long bit;
+	u8 reg;
+
+	bit = simple_strtoul(buf, NULL, 10);
+	if (bit & ~1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	if (bit)
+		data->beep_mask |= (1 << bitnr);
+	else
+		data->beep_mask &= ~(1 << bitnr);
+
+	if (bitnr < 8) {
+		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1);
+		if (bit)
+			reg |= (1 << bitnr);
+		else
+			reg &= ~(1 << bitnr);
+		w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg);
+	} else if (bitnr < 16) {
+		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
+		if (bit)
+			reg |= (1 << (bitnr - 8));
+		else
+			reg &= ~(1 << (bitnr - 8));
+		w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg);
+	} else {
+		reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3);
+		if (bit)
+			reg |= (1 << (bitnr - 16));
+		else
+			reg &= ~(1 << (bitnr - 16));
+		w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 0);
+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 1);
+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 2);
+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 3);
+static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 8);
+static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 9);
+static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 10);
+static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 16);
+static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 17);
+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 6);
+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 7);
+static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 11);
+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 4);
+static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 5);
+static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 13);
+static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+			show_beep, store_beep, 15);
 
 static ssize_t
 show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
@@ -1014,7 +1101,7 @@
 	VAL = sioaddr + 1;
 
 	superio_enter();
-	val= superio_inb(DEVID);
+	val = force_id ? force_id : superio_inb(DEVID);
 	switch (val) {
 	case W627_DEVID:
 		sio_data->type = w83627hf;
@@ -1073,23 +1160,31 @@
 #define VIN_UNIT_ATTRS(_X_)	\
 	&sensor_dev_attr_in##_X_##_input.dev_attr.attr,		\
 	&sensor_dev_attr_in##_X_##_min.dev_attr.attr,		\
-	&sensor_dev_attr_in##_X_##_max.dev_attr.attr
+	&sensor_dev_attr_in##_X_##_max.dev_attr.attr,		\
+	&sensor_dev_attr_in##_X_##_alarm.dev_attr.attr,		\
+	&sensor_dev_attr_in##_X_##_beep.dev_attr.attr
 
 #define FAN_UNIT_ATTRS(_X_)	\
 	&sensor_dev_attr_fan##_X_##_input.dev_attr.attr,	\
 	&sensor_dev_attr_fan##_X_##_min.dev_attr.attr,		\
-	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr
+	&sensor_dev_attr_fan##_X_##_div.dev_attr.attr,		\
+	&sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr,	\
+	&sensor_dev_attr_fan##_X_##_beep.dev_attr.attr
 
 #define TEMP_UNIT_ATTRS(_X_)	\
 	&sensor_dev_attr_temp##_X_##_input.dev_attr.attr,	\
 	&sensor_dev_attr_temp##_X_##_max.dev_attr.attr,		\
 	&sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr,	\
-	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr
+	&sensor_dev_attr_temp##_X_##_type.dev_attr.attr,	\
+	&sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr,	\
+	&sensor_dev_attr_temp##_X_##_beep.dev_attr.attr
 
 static struct attribute *w83627hf_attributes[] = {
 	&dev_attr_in0_input.attr,
 	&dev_attr_in0_min.attr,
 	&dev_attr_in0_max.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in0_beep.dev_attr.attr,
 	VIN_UNIT_ATTRS(2),
 	VIN_UNIT_ATTRS(3),
 	VIN_UNIT_ATTRS(4),
@@ -1103,7 +1198,7 @@
 	TEMP_UNIT_ATTRS(2),
 
 	&dev_attr_alarms.attr,
-	&dev_attr_beep_enable.attr,
+	&sensor_dev_attr_beep_enable.dev_attr.attr,
 	&dev_attr_beep_mask.attr,
 
 	&sensor_dev_attr_pwm1.dev_attr.attr,
@@ -1193,12 +1288,20 @@
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_in5_max.dev_attr))
 		 || (err = device_create_file(dev,
+				&sensor_dev_attr_in5_alarm.dev_attr))
+		 || (err = device_create_file(dev,
+				&sensor_dev_attr_in5_beep.dev_attr))
+		 || (err = device_create_file(dev,
 				&sensor_dev_attr_in6_input.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_in6_min.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_in6_max.dev_attr))
 		 || (err = device_create_file(dev,
+				&sensor_dev_attr_in6_alarm.dev_attr))
+		 || (err = device_create_file(dev,
+				&sensor_dev_attr_in6_beep.dev_attr))
+		 || (err = device_create_file(dev,
 				&sensor_dev_attr_pwm1_freq.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_pwm2_freq.dev_attr)))
@@ -1212,18 +1315,30 @@
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_in1_max.dev_attr))
 		 || (err = device_create_file(dev,
+				&sensor_dev_attr_in1_alarm.dev_attr))
+		 || (err = device_create_file(dev,
+				&sensor_dev_attr_in1_beep.dev_attr))
+		 || (err = device_create_file(dev,
 				&sensor_dev_attr_fan3_input.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_fan3_min.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_fan3_div.dev_attr))
 		 || (err = device_create_file(dev,
+				&sensor_dev_attr_fan3_alarm.dev_attr))
+		 || (err = device_create_file(dev,
+				&sensor_dev_attr_fan3_beep.dev_attr))
+		 || (err = device_create_file(dev,
 				&sensor_dev_attr_temp3_input.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_temp3_max.dev_attr))
 		 || (err = device_create_file(dev,
 				&sensor_dev_attr_temp3_max_hyst.dev_attr))
 		 || (err = device_create_file(dev,
+				&sensor_dev_attr_temp3_alarm.dev_attr))
+		 || (err = device_create_file(dev,
+				&sensor_dev_attr_temp3_beep.dev_attr))
+		 || (err = device_create_file(dev,
 				&sensor_dev_attr_temp3_type.dev_attr)))
 			goto ERROR4;
 
@@ -1511,6 +1626,11 @@
 			    (w83627hf_read_value(data,
 						W83781D_REG_CONFIG) & 0xf7)
 			    | 0x01);
+
+	/* Enable VBAT monitoring if needed */
+	tmp = w83627hf_read_value(data, W83781D_REG_VBAT);
+	if (!(tmp & 0x01))
+		w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01);
 }
 
 static void w83627hf_update_fan_div(struct w83627hf_data *data)
@@ -1603,8 +1723,7 @@
 		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
 		    (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16);
 		i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2);
-		data->beep_enable = i >> 7;
-		data->beep_mask = ((i & 0x7f) << 8) |
+		data->beep_mask = (i << 8) |
 		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) |
 		    w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16;
 		data->last_updated = jiffies;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index e0fa752..7421f6e 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -28,7 +28,6 @@
     as99127f	7	3	0	3	0x31	0x12c3	yes	no
     as99127f rev.2 (type_name = as99127f)	0x31	0x5ca3	yes	no
     w83781d	7	3	0	3	0x10-1	0x5ca3	yes	yes
-    w83627hf	9	3	2	3	0x21	0x5ca3	yes	yes(LPC)
     w83782d	9	3	2-4	3	0x30	0x5ca3	yes	yes
     w83783s	5-6	3	2	1-2	0x40	0x5ca3	yes	no
 
@@ -54,13 +53,12 @@
 static struct platform_device *pdev;
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
-					0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
-					0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
+				       0x2e, 0x2f, I2C_CLIENT_END };
 static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
+I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
 		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -114,7 +112,7 @@
 #define W83781D_REG_ALARM1		0x41
 #define W83781D_REG_ALARM2		0x42
 
-/* Real-time status (W83782D, W83783S, W83627HF) */
+/* Real-time status (W83782D, W83783S) */
 #define W83782D_REG_ALARM1		0x459
 #define W83782D_REG_ALARM2		0x45A
 #define W83782D_REG_ALARM3		0x45B
@@ -153,10 +151,6 @@
 
 #define W83781D_DEFAULT_BETA		3435
 
-/* RT Table registers */
-#define W83781D_REG_RT_IDX		0x50
-#define W83781D_REG_RT_VAL		0x51
-
 /* Conversions */
 #define IN_TO_REG(val)			SENSORS_LIMIT(((val) + 8) / 16, 0, 255)
 #define IN_FROM_REG(val)		((val) * 16)
@@ -271,7 +265,6 @@
 	.driver = {
 		.name = "w83781d",
 	},
-	.id = I2C_DRIVERID_W83781D,
 	.attach_adapter = w83781d_attach_adapter,
 	.detach_client = w83781d_detach_client,
 };
@@ -696,7 +689,7 @@
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
-	
+
 	/* Save fan_min */
 	min = FAN_FROM_REG(data->fan_min[nr],
 			   DIV_FROM_REG(data->fan_div[nr]));
@@ -963,8 +956,6 @@
 		client_name = "w83782d subclient";
 	else if (kind == w83783s)
 		client_name = "w83783s subclient";
-	else if (kind == w83627hf)
-		client_name = "w83627hf subclient";
 	else if (kind == as99127f)
 		client_name = "as99127f subclient";
 
@@ -1004,7 +995,7 @@
 #define IN_UNIT_ATTRS(X)					\
 	&sensor_dev_attr_in##X##_input.dev_attr.attr,		\
 	&sensor_dev_attr_in##X##_min.dev_attr.attr,		\
-	&sensor_dev_attr_in##X##_max.dev_attr.attr, 		\
+	&sensor_dev_attr_in##X##_max.dev_attr.attr,		\
 	&sensor_dev_attr_in##X##_alarm.dev_attr.attr,		\
 	&sensor_dev_attr_in##X##_beep.dev_attr.attr
 
@@ -1268,9 +1259,7 @@
 			kind = w83782d;
 		else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
 			kind = w83783s;
-		else if (val1 == 0x21 && vendid == winbond)
-			kind = w83627hf;
-		else if (val1 == 0x31 && address >= 0x28)
+		else if (val1 == 0x31)
 			kind = as99127f;
 		else {
 			if (kind == 0)
@@ -1288,8 +1277,6 @@
 		client_name = "w83782d";
 	} else if (kind == w83783s) {
 		client_name = "w83783s";
-	} else if (kind == w83627hf) {
-		client_name = "w83627hf";
 	} else if (kind == as99127f) {
 		client_name = "as99127f";
 	}
@@ -1396,10 +1383,6 @@
 
 	reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
 	switch (reg) {
-	case 0x21:
-		data->type = w83627hf;
-		name = "w83627hf";
-		break;
 	case 0x30:
 		data->type = w83782d;
 		name = "w83782d";
@@ -1453,9 +1436,9 @@
 }
 
 /* The SMBus locks itself, usually, but nothing may access the Winbond between
-   bank switches. ISA access must always be locked explicitly! 
+   bank switches. ISA access must always be locked explicitly!
    We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the W83781D access and should not be necessary. 
+   would slow down the W83781D access and should not be necessary.
    There are some ugly typecasts here, but the good news is - they should
    nowhere else be necessary! */
 static int
@@ -1599,11 +1582,6 @@
 	int type = data->type;
 	u8 tmp;
 
-	if (type == w83627hf)
-		dev_info(dev, "The W83627HF chip is better supported by the "
-			 "w83627hf driver, support will be dropped from the "
-			 "w83781d driver soon\n");
-
 	if (reset && type != as99127f) { /* this resets registers we don't have
 					   documentation for on the as99127f */
 		/* Resetting the chip has been the default for a long time,
@@ -1717,8 +1695,7 @@
 			    w83781d_read_value(data, W83781D_REG_IN_MIN(i));
 			data->in_max[i] =
 			    w83781d_read_value(data, W83781D_REG_IN_MAX(i));
-			if ((data->type != w83782d)
-			    && (data->type != w83627hf) && (i == 6))
+			if ((data->type != w83782d) && (i == 6))
 				break;
 		}
 		for (i = 0; i < 3; i++) {
@@ -1776,7 +1753,7 @@
 			data->fan_div[1] |= (i >> 4) & 0x04;
 			data->fan_div[2] |= (i >> 5) & 0x04;
 		}
-		if ((data->type == w83782d) || (data->type == w83627hf)) {
+		if (data->type == w83782d) {
 			data->alarms = w83781d_read_value(data,
 						W83782D_REG_ALARM1)
 				     | (w83781d_read_value(data,
@@ -1886,13 +1863,11 @@
 	outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
 	val = inb_p(address + W83781D_DATA_REG_OFFSET);
 	if ((val & 0xfe) == 0x10	/* W83781D */
-	 || val == 0x30			/* W83782D */
-	 || val == 0x21)		/* W83627HF */
+	 || val == 0x30)		/* W83782D */
 		found = 1;
 
 	if (found)
 		pr_info("w83781d: Found a %s chip at %#x\n",
-			val == 0x21 ? "W83627HF" :
 			val == 0x30 ? "W83782D" : "W83781D", (int)address);
 
  release:
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index a9c01a6..85bd21e 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -840,14 +840,12 @@
 				struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83791d_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	struct w83791d_data *data = dev_get_drvdata(dev);
 
 	/* No lock needed as vrm is internal to the driver
 	   (not read from a chip register) and so is not
 	   updated in w83791d_update_device() */
-	data->vrm = val;
+	data->vrm = simple_strtoul(buf, NULL, 10);
 
 	return count;
 }
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 48599e1..3ba1d6b 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -131,6 +131,7 @@
 #define PWM_DUTY			0
 #define PWM_START			1
 #define PWM_NONSTOP			2
+#define PWM_STOP_TIME			3
 #define W83793_REG_PWM(index, nr)	(((nr) == 0 ? 0xb3 : \
 					 (nr) == 1 ? 0x220 : 0x218) + (index))
 
@@ -242,9 +243,7 @@
 static ssize_t
 show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83793_data *data = i2c_get_clientdata(client);
-
+	struct w83793_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%d\n", data->vrm);
 }
 
@@ -263,9 +262,7 @@
 store_vrm(struct device *dev, struct device_attribute *attr,
 	  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83793_data *data = i2c_get_clientdata(client);
-
+	struct w83793_data *data = dev_get_drvdata(dev);
 	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
@@ -407,10 +404,6 @@
 	return count;
 }
 
-#define PWM_DUTY			0
-#define PWM_START			1
-#define PWM_NONSTOP			2
-#define PWM_STOP_TIME			3
 static ssize_t
 show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index b5db354..1d6259d 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -96,7 +96,6 @@
 	.driver = {
 		.name	= "w83l785ts",
 	},
-	.id		= I2C_DRIVERID_W83L785TS,
 	.attach_adapter	= w83l785ts_attach_adapter,
 	.detach_client	= w83l785ts_detach_client,
 };
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
new file mode 100644
index 0000000..1dbee4f
--- /dev/null
+++ b/drivers/hwmon/w83l786ng.c
@@ -0,0 +1,821 @@
+/*
+    w83l786ng.c - Linux kernel driver for hardware monitoring
+    Copyright (c) 2007 Kevin Lo <kevlo@kevlo.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation - version 2.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301 USA.
+*/
+
+/*
+    Supports following chips:
+
+    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
+    w83l786ng	3	2	2	2	0x7b	0x5ca3	yes	no
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83l786ng);
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
+
+#define W83L786NG_REG_IN_MIN(nr)	(0x2C + (nr) * 2)
+#define W83L786NG_REG_IN_MAX(nr)	(0x2B + (nr) * 2)
+#define W83L786NG_REG_IN(nr)		((nr) + 0x20)
+
+#define W83L786NG_REG_FAN(nr)		((nr) + 0x28)
+#define W83L786NG_REG_FAN_MIN(nr)	((nr) + 0x3B)
+
+#define W83L786NG_REG_CONFIG		0x40
+#define W83L786NG_REG_ALARM1		0x41
+#define W83L786NG_REG_ALARM2 		0x42
+#define W83L786NG_REG_GPIO_EN		0x47
+#define W83L786NG_REG_MAN_ID2		0x4C
+#define W83L786NG_REG_MAN_ID1		0x4D
+#define W83L786NG_REG_CHIP_ID		0x4E
+
+#define W83L786NG_REG_DIODE		0x53
+#define W83L786NG_REG_FAN_DIV		0x54
+#define W83L786NG_REG_FAN_CFG		0x80
+
+#define W83L786NG_REG_TOLERANCE		0x8D
+
+static const u8 W83L786NG_REG_TEMP[2][3] = {
+	{ 0x25,		/* TEMP 0 in DataSheet */
+	  0x35,		/* TEMP 0 Over in DataSheet */
+	  0x36 },	/* TEMP 0 Hyst in DataSheet */
+	{ 0x26,		/* TEMP 1 in DataSheet */
+	  0x37,		/* TEMP 1 Over in DataSheet */
+	  0x38 }	/* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83L786NG_PWM_MODE_SHIFT[] = {6, 7};
+static const u8 W83L786NG_PWM_ENABLE_SHIFT[] = {2, 4};
+
+/* FAN Duty Cycle, be used to control */
+static const u8 W83L786NG_REG_PWM[] = {0x81, 0x87};
+
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+	if (rpm == 0)
+		return 255;
+	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)	((val) == 0   ? -1 : \
+				((val) == 255 ? 0 : \
+				1350000 / ((val) * (div))))
+
+/* for temp */
+#define TEMP_TO_REG(val)	(SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+				    : (val)) / 1000, 0, 0xff))
+#define TEMP_FROM_REG(val)	(((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+
+/* The analog voltage inputs have 8mV LSB. Since the sysfs output is
+   in mV as would be measured on the chip input pin, need to just
+   multiply/divide by 8 to translate from/to register values. */
+#define IN_TO_REG(val)          (SENSORS_LIMIT((((val) + 4) / 8), 0, 255))
+#define IN_FROM_REG(val)	((val) * 8)
+
+#define DIV_FROM_REG(val)	(1 << (val))
+
+static inline u8
+DIV_TO_REG(long val)
+{
+	int i;
+	val = SENSORS_LIMIT(val, 1, 128) >> 1;
+	for (i = 0; i < 7; i++) {
+		if (val == 0)
+			break;
+		val >>= 1;
+	}
+	return ((u8) i);
+}
+
+struct w83l786ng_data {
+	struct i2c_client client;
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	unsigned long last_nonvolatile;	/* In jiffies, last time we update the
+					   nonvolatile registers */
+
+	u8 in[3];
+	u8 in_max[3];
+	u8 in_min[3];
+	u8 fan[2];
+	u8 fan_div[2];
+	u8 fan_min[2];
+	u8 temp_type[2];
+	u8 temp[2][3];
+	u8 pwm[2];
+	u8 pwm_mode[2];	/* 0->DC variable voltage
+			   1->PWM variable duty cycle */
+
+	u8 pwm_enable[2]; /* 1->manual
+			     2->thermal cruise (also called SmartFan I) */
+	u8 tolerance[2];
+};
+
+static int w83l786ng_attach_adapter(struct i2c_adapter *adapter);
+static int w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83l786ng_detach_client(struct i2c_client *client);
+static void w83l786ng_init_client(struct i2c_client *client);
+static struct w83l786ng_data *w83l786ng_update_device(struct device *dev);
+
+static struct i2c_driver w83l786ng_driver = {
+	.driver = {
+		   .name = "w83l786ng",
+	},
+	.attach_adapter = w83l786ng_attach_adapter,
+	.detach_client = w83l786ng_detach_client,
+};
+
+static u8
+w83l786ng_read_value(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int
+w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* following are the sysfs callback functions */
+#define show_in_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, struct device_attribute *attr, \
+           char *buf) \
+{ \
+	int nr = to_sensor_dev_attr(attr)->index; \
+	struct w83l786ng_data *data = w83l786ng_update_device(dev); \
+	return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \
+}
+
+show_in_reg(in)
+show_in_reg(in_min)
+show_in_reg(in_max)
+
+#define store_in_reg(REG, reg) \
+static ssize_t \
+store_in_##reg (struct device *dev, struct device_attribute *attr, \
+		const char *buf, size_t count) \
+{ \
+	int nr = to_sensor_dev_attr(attr)->index; \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83l786ng_data *data = i2c_get_clientdata(client); \
+	unsigned long val = simple_strtoul(buf, NULL, 10); \
+	mutex_lock(&data->update_lock); \
+	data->in_##reg[nr] = IN_TO_REG(val); \
+	w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \
+			      data->in_##reg[nr]); \
+	mutex_unlock(&data->update_lock); \
+	return count; \
+}
+
+store_in_reg(MIN, min)
+store_in_reg(MAX, max)
+
+static struct sensor_device_attribute sda_in_input[] = {
+	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+};
+
+static struct sensor_device_attribute sda_in_min[] = {
+	SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+	SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+	SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+};
+
+static struct sensor_device_attribute sda_in_max[] = {
+	SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+	SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+	SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+};
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+			  char *buf) \
+{ \
+	int nr = to_sensor_dev_attr(attr)->index; \
+	struct w83l786ng_data *data = w83l786ng_update_device(dev); \
+        return sprintf(buf,"%d\n", \
+                FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	mutex_lock(&data->update_lock);
+	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+	w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr),
+			      data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr,
+	     char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct w83l786ng_data *data = w83l786ng_update_device(dev);
+	return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least surprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t
+store_fan_div(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+
+	unsigned long min;
+	u8 tmp_fan_div;
+	u8 fan_div_reg;
+	u8 keep_mask = 0;
+	u8 new_shift = 0;
+
+	/* Save fan_min */
+	mutex_lock(&data->update_lock);
+	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
+
+	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+	switch (nr) {
+	case 0:
+		keep_mask = 0xf8;
+		new_shift = 0;
+		break;
+	case 1:
+		keep_mask = 0x8f;
+		new_shift = 4;
+		break;
+	}
+
+	fan_div_reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV)
+					   & keep_mask;
+
+	tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask;
+
+	w83l786ng_write_value(client, W83L786NG_REG_FAN_DIV,
+			      fan_div_reg | tmp_fan_div);
+
+	/* Restore fan_min */
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr),
+			      data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute sda_fan_input[] = {
+	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
+	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
+};
+
+static struct sensor_device_attribute sda_fan_min[] = {
+	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 0),
+	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 1),
+};
+
+static struct sensor_device_attribute sda_fan_div[] = {
+	SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div,
+		    store_fan_div, 0),
+	SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div,
+		    store_fan_div, 1),
+};
+
+
+/* read/write the temperature, includes measured value and limits */
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83l786ng_data *data = w83l786ng_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index]));
+}
+
+static ssize_t
+store_temp(struct device *dev, struct device_attribute *attr,
+	   const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr =
+	    to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	s32 val;
+
+	val = simple_strtol(buf, NULL, 10);
+	mutex_lock(&data->update_lock);
+	data->temp[nr][index] = TEMP_TO_REG(val);
+	w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index],
+			      data->temp[nr][index]);
+	mutex_unlock(&data->update_lock);
+
+        return count;
+}
+
+static struct sensor_device_attribute_2 sda_temp_input[] = {
+	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
+	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max[] = {
+	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
+		      show_temp, store_temp, 0, 1),
+	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR,
+		      show_temp, store_temp, 1, 1),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
+	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
+		      show_temp, store_temp, 0, 2),
+	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
+		      show_temp, store_temp, 1, 2),
+};
+
+#define show_pwm_reg(reg) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+			   char *buf) \
+{ \
+	struct w83l786ng_data *data = w83l786ng_update_device(dev); \
+	int nr = to_sensor_dev_attr(attr)->index; \
+	return sprintf(buf, "%d\n", data->reg[nr]); \
+}
+
+show_pwm_reg(pwm_mode)
+show_pwm_reg(pwm_enable)
+show_pwm_reg(pwm)
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 reg;
+
+	if (val > 1)
+		return -EINVAL;
+	mutex_lock(&data->update_lock);
+	data->pwm_mode[nr] = val;
+	reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
+	reg &= ~(1 << W83L786NG_PWM_MODE_SHIFT[nr]);
+	if (!val)
+		reg |= 1 << W83L786NG_PWM_MODE_SHIFT[nr];
+	w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+	  const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->pwm[nr] = val;
+	w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+store_pwm_enable(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	u8 reg;
+
+	if (!val || (val > 2))  /* only modes 1 and 2 are supported */
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
+	data->pwm_enable[nr] = val;
+	reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
+	reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr];
+	w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static struct sensor_device_attribute sda_pwm[] = {
+	SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
+	SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
+};
+
+static struct sensor_device_attribute sda_pwm_mode[] = {
+	SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+		    store_pwm_mode, 0),
+	SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+		    store_pwm_mode, 1),
+};
+
+static struct sensor_device_attribute sda_pwm_enable[] = {
+	SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+		    store_pwm_enable, 0),
+	SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+		    store_pwm_enable, 1),
+};
+
+/* For Smart Fan I/Thermal Cruise and Smart Fan II */
+static ssize_t
+show_tolerance(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct w83l786ng_data *data = w83l786ng_update_device(dev);
+	return sprintf(buf, "%ld\n", (long)data->tolerance[nr]);
+}
+
+static ssize_t
+store_tolerance(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 tol_tmp, tol_mask;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	tol_mask = w83l786ng_read_value(client,
+	    W83L786NG_REG_TOLERANCE) & ((nr == 1) ? 0x0f : 0xf0);
+	tol_tmp = SENSORS_LIMIT(val, 0, 15);
+	tol_tmp &= 0x0f;
+	data->tolerance[nr] = tol_tmp;
+	if (nr == 1) {
+		tol_tmp <<= 4;
+	}
+
+	w83l786ng_write_value(client, W83L786NG_REG_TOLERANCE,
+			      tol_mask | tol_tmp);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static struct sensor_device_attribute sda_tolerance[] = {
+	SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO,
+		    show_tolerance, store_tolerance, 0),
+	SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO,
+		    show_tolerance, store_tolerance, 1),
+};
+
+
+#define IN_UNIT_ATTRS(X)	\
+	&sda_in_input[X].dev_attr.attr,		\
+	&sda_in_min[X].dev_attr.attr,		\
+	&sda_in_max[X].dev_attr.attr
+
+#define FAN_UNIT_ATTRS(X)	\
+	&sda_fan_input[X].dev_attr.attr,	\
+	&sda_fan_min[X].dev_attr.attr,		\
+	&sda_fan_div[X].dev_attr.attr
+
+#define TEMP_UNIT_ATTRS(X)	\
+	&sda_temp_input[X].dev_attr.attr,	\
+	&sda_temp_max[X].dev_attr.attr,		\
+	&sda_temp_max_hyst[X].dev_attr.attr
+
+#define PWM_UNIT_ATTRS(X)	\
+	&sda_pwm[X].dev_attr.attr,		\
+	&sda_pwm_mode[X].dev_attr.attr,		\
+	&sda_pwm_enable[X].dev_attr.attr
+
+#define TOLERANCE_UNIT_ATTRS(X)	\
+	&sda_tolerance[X].dev_attr.attr
+
+static struct attribute *w83l786ng_attributes[] = {
+	IN_UNIT_ATTRS(0),
+	IN_UNIT_ATTRS(1),
+	IN_UNIT_ATTRS(2),
+	FAN_UNIT_ATTRS(0),
+	FAN_UNIT_ATTRS(1),
+	TEMP_UNIT_ATTRS(0),
+	TEMP_UNIT_ATTRS(1),
+	PWM_UNIT_ATTRS(0),
+	PWM_UNIT_ATTRS(1),
+	TOLERANCE_UNIT_ATTRS(0),
+	TOLERANCE_UNIT_ATTRS(1),
+	NULL
+};
+
+static const struct attribute_group w83l786ng_group = {
+	.attrs = w83l786ng_attributes,
+};
+
+static int
+w83l786ng_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, w83l786ng_detect);
+}
+
+static int
+w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct device *dev;
+	struct w83l786ng_data *data;
+	int i, err = 0;
+	u8 reg_tmp;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		goto exit;
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access w83l786ng_{read,write}_value. */
+
+	if (!(data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	dev = &client->dev;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &w83l786ng_driver;
+
+	/*
+	 * Now we do the remaining detection. A negative kind means that
+	 * the driver was loaded with no force parameter (default), so we
+	 * must both detect and identify the chip (actually there is only
+	 * one possible kind of chip for now, W83L786NG). A zero kind means
+	 * that the driver was loaded with the force parameter, the detection
+	 * step shall be skipped. A positive kind means that the driver
+	 * was loaded with the force parameter and a given kind of chip is
+	 * requested, so both the detection and the identification steps
+	 * are skipped.
+	 */
+	if (kind < 0) { /* detection */
+		if (((w83l786ng_read_value(client,
+		    W83L786NG_REG_CONFIG) & 0x80) != 0x00)) {
+			dev_dbg(&adapter->dev,
+				"W83L786NG detection failed at 0x%02x.\n",
+				address);
+			goto exit_free;
+		}
+	}
+
+	if (kind <= 0) { /* identification */
+		u16 man_id;
+		u8 chip_id;
+
+		man_id = (w83l786ng_read_value(client,
+		    W83L786NG_REG_MAN_ID1) << 8) +
+		    w83l786ng_read_value(client, W83L786NG_REG_MAN_ID2);
+		chip_id = w83l786ng_read_value(client, W83L786NG_REG_CHIP_ID);
+
+		if (man_id == 0x5CA3) { /* Winbond */
+			if (chip_id == 0x80) { /* W83L786NG */
+				kind = w83l786ng;
+			}
+		}
+
+		if (kind <= 0) { /* identification failed */
+			dev_info(&adapter->dev,
+			    "Unsupported chip (man_id=0x%04X, "
+			    "chip_id=0x%02X).\n", man_id, chip_id);
+			goto exit_free;
+		}
+	}
+
+	/* Fill in the remaining client fields and put into the global list */
+	strlcpy(client->name, "w83l786ng", I2C_NAME_SIZE);
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto exit_free;
+
+	/* Initialize the chip */
+	w83l786ng_init_client(client);
+
+	/* A few vars need to be filled upon startup */
+	for (i = 0; i < 2; i++) {
+		data->fan_min[i] = w83l786ng_read_value(client,
+		    W83L786NG_REG_FAN_MIN(i));
+	}
+
+	/* Update the fan divisor */
+	reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV);
+	data->fan_div[0] = reg_tmp & 0x07;
+	data->fan_div[1] = (reg_tmp >> 4) & 0x07;
+
+	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group)))
+		goto exit_remove;
+
+	data->hwmon_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+	/* Unregister sysfs hooks */
+
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
+	i2c_detach_client(client);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int
+w83l786ng_detach_client(struct i2c_client *client)
+{
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	int err;
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
+
+	return 0;
+}
+
+static void
+w83l786ng_init_client(struct i2c_client *client)
+{
+	u8 tmp;
+
+	if (reset)
+		w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80);
+
+	/* Start monitoring */
+	tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG);
+	if (!(tmp & 0x01))
+		w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01);
+}
+
+static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83l786ng_data *data = i2c_get_clientdata(client);
+	int i, j;
+	u8 reg_tmp, pwmcfg;
+
+	mutex_lock(&data->update_lock);
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		dev_dbg(&client->dev, "Updating w83l786ng data.\n");
+
+		/* Update the voltages measured value and limits */
+		for (i = 0; i < 3; i++) {
+			data->in[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_IN(i));
+			data->in_min[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_IN_MIN(i));
+			data->in_max[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_IN_MAX(i));
+		}
+
+		/* Update the fan counts and limits */
+		for (i = 0; i < 2; i++) {
+			data->fan[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_FAN(i));
+			data->fan_min[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_FAN_MIN(i));
+		}
+
+		/* Update the fan divisor */
+		reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV);
+		data->fan_div[0] = reg_tmp & 0x07;
+		data->fan_div[1] = (reg_tmp >> 4) & 0x07;
+
+		pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
+		for (i = 0; i < 2; i++) {
+			data->pwm_mode[i] =
+			    ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
+			    ? 0 : 1;
+			data->pwm_enable[i] =
+			    ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1;
+			data->pwm[i] = w83l786ng_read_value(client,
+			    W83L786NG_REG_PWM[i]);
+		}
+
+
+		/* Update the temperature sensors */
+		for (i = 0; i < 2; i++) {
+			for (j = 0; j < 3; j++) {
+				data->temp[i][j] = w83l786ng_read_value(client,
+				    W83L786NG_REG_TEMP[i][j]);
+			}
+		}
+
+		/* Update Smart Fan I/II tolerance */
+		reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE);
+		data->tolerance[0] = reg_tmp & 0x0f;
+		data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static int __init
+sensors_w83l786ng_init(void)
+{
+	return i2c_add_driver(&w83l786ng_driver);
+}
+
+static void __exit
+sensors_w83l786ng_exit(void)
+{
+	i2c_del_driver(&w83l786ng_driver);
+}
+
+MODULE_AUTHOR("Kevin Lo");
+MODULE_DESCRIPTION("w83l786ng driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83l786ng_init);
+module_exit(sensors_w83l786ng_exit);
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index fde297b2..7dee001 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -71,7 +71,6 @@
 	.driver = {
 		.name	= "eeprom",
 	},
-	.id		= I2C_DRIVERID_EEPROM,
 	.attach_adapter	= eeprom_attach_adapter,
 	.detach_client	= eeprom_detach_client,
 };
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index b3b830c..e5b3132 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -67,7 +67,6 @@
 	.driver = {
 		.name	= "pcf8574",
 	},
-	.id		= I2C_DRIVERID_PCF8574,
 	.attach_adapter	= pcf8574_attach_adapter,
 	.detach_client	= pcf8574_detach_client,
 };
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 865f440..66c7c3b 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -92,7 +92,6 @@
 	.driver = {
 		.name	= "pcf8591",
 	},
-	.id		= I2C_DRIVERID_PCF8591,
 	.attach_adapter	= pcf8591_attach_adapter,
 	.detach_client	= pcf8591_detach_client,
 };
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 78cd338..7b5220c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -285,4 +285,13 @@
 
 	  If unsure, say N.
 
+config ENCLOSURE_SERVICES
+	tristate "Enclosure Services"
+	default n
+	help
+	  Provides support for intelligent enclosures (bays which
+	  contain storage devices).  You also need either a host
+	  driver (SCSI/ATA) which supports enclosures
+	  or a SCSI enclosure device (SES) to use these services.
+
 endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 1f41654..7f13549 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -20,3 +20,4 @@
 obj-$(CONFIG_FUJITSU_LAPTOP)	+= fujitsu-laptop.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_INTEL_MENLOW)	+= intel_menlow.o
+obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
new file mode 100644
index 0000000..6fcb0e9
--- /dev/null
+++ b/drivers/misc/enclosure.c
@@ -0,0 +1,484 @@
+/*
+ * Enclosure Services
+ *
+ * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ *
+**-----------------------------------------------------------------------------
+**
+**  This program is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU General Public License
+**  version 2 as published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+*/
+#include <linux/device.h>
+#include <linux/enclosure.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+static LIST_HEAD(container_list);
+static DEFINE_MUTEX(container_list_lock);
+static struct class enclosure_class;
+static struct class enclosure_component_class;
+
+/**
+ * enclosure_find - find an enclosure given a device
+ * @dev:	the device to find for
+ *
+ * Looks through the list of registered enclosures to see
+ * if it can find a match for a device.  Returns NULL if no
+ * enclosure is found. Obtains a reference to the enclosure class
+ * device which must be released with class_device_put().
+ */
+struct enclosure_device *enclosure_find(struct device *dev)
+{
+	struct enclosure_device *edev = NULL;
+
+	mutex_lock(&container_list_lock);
+	list_for_each_entry(edev, &container_list, node) {
+		if (edev->cdev.dev == dev) {
+			class_device_get(&edev->cdev);
+			mutex_unlock(&container_list_lock);
+			return edev;
+		}
+	}
+	mutex_unlock(&container_list_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(enclosure_find);
+
+/**
+ * enclosure_for_each_device - calls a function for each enclosure
+ * @fn:		the function to call
+ * @data:	the data to pass to each call
+ *
+ * Loops over all the enclosures calling the function.
+ *
+ * Note, this function uses a mutex which will be held across calls to
+ * @fn, so it must have non atomic context, and @fn may (although it
+ * should not) sleep or otherwise cause the mutex to be held for
+ * indefinite periods
+ */
+int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
+			      void *data)
+{
+	int error = 0;
+	struct enclosure_device *edev;
+
+	mutex_lock(&container_list_lock);
+	list_for_each_entry(edev, &container_list, node) {
+		error = fn(edev, data);
+		if (error)
+			break;
+	}
+	mutex_unlock(&container_list_lock);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(enclosure_for_each_device);
+
+/**
+ * enclosure_register - register device as an enclosure
+ *
+ * @dev:	device containing the enclosure
+ * @components:	number of components in the enclosure
+ *
+ * This sets up the device for being an enclosure.  Note that @dev does
+ * not have to be a dedicated enclosure device.  It may be some other type
+ * of device that additionally responds to enclosure services
+ */
+struct enclosure_device *
+enclosure_register(struct device *dev, const char *name, int components,
+		   struct enclosure_component_callbacks *cb)
+{
+	struct enclosure_device *edev =
+		kzalloc(sizeof(struct enclosure_device) +
+			sizeof(struct enclosure_component)*components,
+			GFP_KERNEL);
+	int err, i;
+
+	BUG_ON(!cb);
+
+	if (!edev)
+		return ERR_PTR(-ENOMEM);
+
+	edev->components = components;
+
+	edev->cdev.class = &enclosure_class;
+	edev->cdev.dev = get_device(dev);
+	edev->cb = cb;
+	snprintf(edev->cdev.class_id, BUS_ID_SIZE, "%s", name);
+	err = class_device_register(&edev->cdev);
+	if (err)
+		goto err;
+
+	for (i = 0; i < components; i++)
+		edev->component[i].number = -1;
+
+	mutex_lock(&container_list_lock);
+	list_add_tail(&edev->node, &container_list);
+	mutex_unlock(&container_list_lock);
+
+	return edev;
+
+ err:
+	put_device(edev->cdev.dev);
+	kfree(edev);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(enclosure_register);
+
+static struct enclosure_component_callbacks enclosure_null_callbacks;
+
+/**
+ * enclosure_unregister - remove an enclosure
+ *
+ * @edev:	the registered enclosure to remove;
+ */
+void enclosure_unregister(struct enclosure_device *edev)
+{
+	int i;
+
+	mutex_lock(&container_list_lock);
+	list_del(&edev->node);
+	mutex_unlock(&container_list_lock);
+
+	for (i = 0; i < edev->components; i++)
+		if (edev->component[i].number != -1)
+			class_device_unregister(&edev->component[i].cdev);
+
+	/* prevent any callbacks into service user */
+	edev->cb = &enclosure_null_callbacks;
+	class_device_unregister(&edev->cdev);
+}
+EXPORT_SYMBOL_GPL(enclosure_unregister);
+
+static void enclosure_release(struct class_device *cdev)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev);
+
+	put_device(cdev->dev);
+	kfree(edev);
+}
+
+static void enclosure_component_release(struct class_device *cdev)
+{
+	if (cdev->dev)
+		put_device(cdev->dev);
+	class_device_put(cdev->parent);
+}
+
+/**
+ * enclosure_component_register - add a particular component to an enclosure
+ * @edev:	the enclosure to add the component
+ * @num:	the device number
+ * @type:	the type of component being added
+ * @name:	an optional name to appear in sysfs (leave NULL if none)
+ *
+ * Registers the component.  The name is optional for enclosures that
+ * give their components a unique name.  If not, leave the field NULL
+ * and a name will be assigned.
+ *
+ * Returns a pointer to the enclosure component or an error.
+ */
+struct enclosure_component *
+enclosure_component_register(struct enclosure_device *edev,
+			     unsigned int number,
+			     enum enclosure_component_type type,
+			     const char *name)
+{
+	struct enclosure_component *ecomp;
+	struct class_device *cdev;
+	int err;
+
+	if (number >= edev->components)
+		return ERR_PTR(-EINVAL);
+
+	ecomp = &edev->component[number];
+
+	if (ecomp->number != -1)
+		return ERR_PTR(-EINVAL);
+
+	ecomp->type = type;
+	ecomp->number = number;
+	cdev = &ecomp->cdev;
+	cdev->parent = class_device_get(&edev->cdev);
+	cdev->class = &enclosure_component_class;
+	if (name)
+		snprintf(cdev->class_id, BUS_ID_SIZE, "%s", name);
+	else
+		snprintf(cdev->class_id, BUS_ID_SIZE, "%u", number);
+
+	err = class_device_register(cdev);
+	if (err)
+		ERR_PTR(err);
+
+	return ecomp;
+}
+EXPORT_SYMBOL_GPL(enclosure_component_register);
+
+/**
+ * enclosure_add_device - add a device as being part of an enclosure
+ * @edev:	the enclosure device being added to.
+ * @num:	the number of the component
+ * @dev:	the device being added
+ *
+ * Declares a real device to reside in slot (or identifier) @num of an
+ * enclosure.  This will cause the relevant sysfs links to appear.
+ * This function may also be used to change a device associated with
+ * an enclosure without having to call enclosure_remove_device() in
+ * between.
+ *
+ * Returns zero on success or an error.
+ */
+int enclosure_add_device(struct enclosure_device *edev, int component,
+			 struct device *dev)
+{
+	struct class_device *cdev;
+
+	if (!edev || component >= edev->components)
+		return -EINVAL;
+
+	cdev = &edev->component[component].cdev;
+
+	class_device_del(cdev);
+	if (cdev->dev)
+		put_device(cdev->dev);
+	cdev->dev = get_device(dev);
+	return class_device_add(cdev);
+}
+EXPORT_SYMBOL_GPL(enclosure_add_device);
+
+/**
+ * enclosure_remove_device - remove a device from an enclosure
+ * @edev:	the enclosure device
+ * @num:	the number of the component to remove
+ *
+ * Returns zero on success or an error.
+ *
+ */
+int enclosure_remove_device(struct enclosure_device *edev, int component)
+{
+	struct class_device *cdev;
+
+	if (!edev || component >= edev->components)
+		return -EINVAL;
+
+	cdev = &edev->component[component].cdev;
+
+	class_device_del(cdev);
+	if (cdev->dev)
+		put_device(cdev->dev);
+	cdev->dev = NULL;
+	return class_device_add(cdev);
+}
+EXPORT_SYMBOL_GPL(enclosure_remove_device);
+
+/*
+ * sysfs pieces below
+ */
+
+static ssize_t enclosure_show_components(struct class_device *cdev, char *buf)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev);
+
+	return snprintf(buf, 40, "%d\n", edev->components);
+}
+
+static struct class_device_attribute enclosure_attrs[] = {
+	__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
+	__ATTR_NULL
+};
+
+static struct class enclosure_class = {
+	.name			= "enclosure",
+	.owner			= THIS_MODULE,
+	.release		= enclosure_release,
+	.class_dev_attrs	= enclosure_attrs,
+};
+
+static const char *const enclosure_status [] = {
+	[ENCLOSURE_STATUS_UNSUPPORTED] = "unsupported",
+	[ENCLOSURE_STATUS_OK] = "OK",
+	[ENCLOSURE_STATUS_CRITICAL] = "critical",
+	[ENCLOSURE_STATUS_NON_CRITICAL] = "non-critical",
+	[ENCLOSURE_STATUS_UNRECOVERABLE] = "unrecoverable",
+	[ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
+	[ENCLOSURE_STATUS_UNKNOWN] = "unknown",
+	[ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
+};
+
+static const char *const enclosure_type [] = {
+	[ENCLOSURE_COMPONENT_DEVICE] = "device",
+	[ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
+};
+
+static ssize_t get_component_fault(struct class_device *cdev, char *buf)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+	if (edev->cb->get_fault)
+		edev->cb->get_fault(edev, ecomp);
+	return snprintf(buf, 40, "%d\n", ecomp->fault);
+}
+
+static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
+				   size_t count)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+	int val = simple_strtoul(buf, NULL, 0);
+
+	if (edev->cb->set_fault)
+		edev->cb->set_fault(edev, ecomp, val);
+	return count;
+}
+
+static ssize_t get_component_status(struct class_device *cdev, char *buf)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+	if (edev->cb->get_status)
+		edev->cb->get_status(edev, ecomp);
+	return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
+}
+
+static ssize_t set_component_status(struct class_device *cdev, const char *buf,
+				   size_t count)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+	int i;
+
+	for (i = 0; enclosure_status[i]; i++) {
+		if (strncmp(buf, enclosure_status[i],
+			    strlen(enclosure_status[i])) == 0 &&
+		    (buf[strlen(enclosure_status[i])] == '\n' ||
+		     buf[strlen(enclosure_status[i])] == '\0'))
+			break;
+	}
+
+	if (enclosure_status[i] && edev->cb->set_status) {
+		edev->cb->set_status(edev, ecomp, i);
+		return count;
+	} else
+		return -EINVAL;
+}
+
+static ssize_t get_component_active(struct class_device *cdev, char *buf)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+	if (edev->cb->get_active)
+		edev->cb->get_active(edev, ecomp);
+	return snprintf(buf, 40, "%d\n", ecomp->active);
+}
+
+static ssize_t set_component_active(struct class_device *cdev, const char *buf,
+				   size_t count)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+	int val = simple_strtoul(buf, NULL, 0);
+
+	if (edev->cb->set_active)
+		edev->cb->set_active(edev, ecomp, val);
+	return count;
+}
+
+static ssize_t get_component_locate(struct class_device *cdev, char *buf)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+	if (edev->cb->get_locate)
+		edev->cb->get_locate(edev, ecomp);
+	return snprintf(buf, 40, "%d\n", ecomp->locate);
+}
+
+static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
+				   size_t count)
+{
+	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+	int val = simple_strtoul(buf, NULL, 0);
+
+	if (edev->cb->set_locate)
+		edev->cb->set_locate(edev, ecomp, val);
+	return count;
+}
+
+static ssize_t get_component_type(struct class_device *cdev, char *buf)
+{
+	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+	return snprintf(buf, 40, "%s\n", enclosure_type[ecomp->type]);
+}
+
+
+static struct class_device_attribute enclosure_component_attrs[] = {
+	__ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
+	       set_component_fault),
+	__ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
+	       set_component_status),
+	__ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
+	       set_component_active),
+	__ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
+	       set_component_locate),
+	__ATTR(type, S_IRUGO, get_component_type, NULL),
+	__ATTR_NULL
+};
+
+static struct class enclosure_component_class =  {
+	.name			= "enclosure_component",
+	.owner			= THIS_MODULE,
+	.class_dev_attrs	= enclosure_component_attrs,
+	.release		= enclosure_component_release,
+};
+
+static int __init enclosure_init(void)
+{
+	int err;
+
+	err = class_register(&enclosure_class);
+	if (err)
+		return err;
+	err = class_register(&enclosure_component_class);
+	if (err)
+		goto err_out;
+
+	return 0;
+ err_out:
+	class_unregister(&enclosure_class);
+
+	return err;
+}
+
+static void __exit enclosure_exit(void)
+{
+	class_unregister(&enclosure_component_class);
+	class_unregister(&enclosure_class);
+}
+
+module_init(enclosure_init);
+module_exit(enclosure_exit);
+
+MODULE_AUTHOR("James Bottomley");
+MODULE_DESCRIPTION("Enclosure Services");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 14fc7f3..a5f0aaa 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -179,7 +179,15 @@
 	  say M here and read <file:Documentation/kbuild/modules.txt> and
 	  <file:Documentation/scsi/scsi.txt>. The module will be called ch.o.
 	  If unsure, say N.
-	
+
+config SCSI_ENCLOSURE
+	tristate "SCSI Enclosure Support"
+	depends on SCSI && ENCLOSURE_SERVICES
+	help
+	  Enclosures are devices sitting on or in SCSI backplanes that
+	  manage devices.  If you have a disk cage, the chances are that
+	  it has an enclosure device.  Selecting this option will just allow
+	  certain enclosure conditions to be reported and is not required.
 
 comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
 	depends on SCSI
@@ -350,17 +358,6 @@
 	  If you have a Western Digital WD93 SCSI controller on
 	  an SGI MIPS system, say Y.  Otherwise, say N.
 
-config SCSI_DECNCR
-	tristate "DEC NCR53C94 Scsi Driver"
-	depends on MACH_DECSTATION && SCSI && TC
-	help
-	  Say Y here to support the NCR53C94 SCSI controller chips on IOASIC
-	  based TURBOchannel DECstations and TURBOchannel PMAZ-A cards.
-
-config SCSI_DECSII
-	tristate "DEC SII Scsi Driver"
-	depends on MACH_DECSTATION && SCSI && 32BIT
-
 config BLK_DEV_3W_XXXX_RAID
 	tristate "3ware 5/6/7/8xxx ATA-RAID support"
 	depends on PCI && SCSI
@@ -1263,17 +1260,6 @@
 	  not allow targets to disconnect is not reasonable if there is more
 	  than 1 device on a SCSI bus. The normal answer therefore is N.
 
-config SCSI_MCA_53C9X
-	tristate "NCR MCA 53C9x SCSI support"
-	depends on MCA_LEGACY && SCSI && BROKEN_ON_SMP
-	help
-	  Some MicroChannel machines, notably the NCR 35xx line, use a SCSI
-	  controller based on the NCR 53C94.  This driver will allow use of
-	  the controller on the 3550, and very possibly others.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mca_53c9x.
-
 config SCSI_PAS16
 	tristate "PAS16 SCSI support"
 	depends on ISA && SCSI
@@ -1600,45 +1586,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gvp11.
 
-config CYBERSTORM_SCSI
-	tristate "CyberStorm SCSI support"
-	depends on ZORRO && SCSI
-	help
-	  If you have an Amiga with an original (MkI) Phase5 Cyberstorm
-	  accelerator board and the optional Cyberstorm SCSI controller,
-	  answer Y. Otherwise, say N.
-
-config CYBERSTORMII_SCSI
-	tristate "CyberStorm Mk II SCSI support"
-	depends on ZORRO && SCSI
-	help
-	  If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board
-	  and the optional Cyberstorm SCSI controller, say Y. Otherwise,
-	  answer N.
-
-config BLZ2060_SCSI
-	tristate "Blizzard 2060 SCSI support"
-	depends on ZORRO && SCSI
-	help
-	  If you have an Amiga with a Phase5 Blizzard 2060 accelerator board
-	  and want to use the onboard SCSI controller, say Y. Otherwise,
-	  answer N.
-
-config BLZ1230_SCSI
-	tristate "Blizzard 1230IV/1260 SCSI support"
-	depends on ZORRO && SCSI
-	help
-	  If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard
-	  1260 accelerator, and the optional SCSI module, say Y. Otherwise,
-	  say N.
-
-config FASTLANE_SCSI
-	tristate "Fastlane SCSI support"
-	depends on ZORRO && SCSI
-	help
-	  If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
-	  one in the near future, say Y to this question. Otherwise, say N.
-
 config SCSI_A4000T
 	tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
 	depends on AMIGA && SCSI && EXPERIMENTAL
@@ -1666,15 +1613,6 @@
 	      accelerator card for the Amiga 1200,
 	    - the SCSI controller on the GVP Turbo 040/060 accelerator.
 
-config OKTAGON_SCSI
-	tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
-	depends on ZORRO && SCSI && EXPERIMENTAL
-	help
-	  If you have the BSC Oktagon SCSI disk controller for the Amiga, say
-	  Y to this question.  If you're in doubt about whether you have one,
-	  see the picture at
-	  <http://amiga.resource.cx/exp/search.pl?product=oktagon>.
-
 config ATARI_SCSI
 	tristate "Atari native SCSI support"
 	depends on ATARI && SCSI
@@ -1727,18 +1665,6 @@
 	  SCSI-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
-config SCSI_MAC_ESP
-	tristate "Macintosh NCR53c9[46] SCSI"
-	depends on MAC && SCSI
-	help
-	  This is the NCR 53c9x SCSI controller found on most of the 68040
-	  based Macintoshes.  If you have one of these say Y and read the
-	  SCSI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mac_esp.
-
 config MVME147_SCSI
 	bool "WD33C93 SCSI driver for MVME147"
 	depends on MVME147 && SCSI=y
@@ -1779,6 +1705,7 @@
 config SUN3X_ESP
 	bool "Sun3x ESP SCSI"
 	depends on SUN3X && SCSI=y
+	select SCSI_SPI_ATTRS
 	help
 	  The ESP was an on-board SCSI controller used on Sun 3/80
 	  machines.  Say Y here to compile in support for it.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 93e1428..925c26b 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -44,15 +44,8 @@
 obj-$(CONFIG_GVP11_SCSI)	+= gvp11.o	wd33c93.o
 obj-$(CONFIG_MVME147_SCSI)	+= mvme147.o	wd33c93.o
 obj-$(CONFIG_SGIWD93_SCSI)	+= sgiwd93.o	wd33c93.o
-obj-$(CONFIG_CYBERSTORM_SCSI)	+= NCR53C9x.o	cyberstorm.o
-obj-$(CONFIG_CYBERSTORMII_SCSI)	+= NCR53C9x.o	cyberstormII.o
-obj-$(CONFIG_BLZ2060_SCSI)	+= NCR53C9x.o	blz2060.o
-obj-$(CONFIG_BLZ1230_SCSI)	+= NCR53C9x.o	blz1230.o
-obj-$(CONFIG_FASTLANE_SCSI)	+= NCR53C9x.o	fastlane.o
-obj-$(CONFIG_OKTAGON_SCSI)	+= NCR53C9x.o	oktagon_esp_mod.o
 obj-$(CONFIG_ATARI_SCSI)	+= atari_scsi.o
 obj-$(CONFIG_MAC_SCSI)		+= mac_scsi.o
-obj-$(CONFIG_SCSI_MAC_ESP)	+= mac_esp.o	NCR53C9x.o
 obj-$(CONFIG_SUN3_SCSI)		+= sun3_scsi.o  sun3_scsi_vme.o
 obj-$(CONFIG_MVME16x_SCSI)	+= 53c700.o	mvme16x_scsi.o
 obj-$(CONFIG_BVME6000_SCSI)	+= 53c700.o	bvme6000_scsi.o
@@ -95,7 +88,6 @@
 obj-$(CONFIG_SCSI_ZALON)	+= zalon7xx.o
 obj-$(CONFIG_SCSI_EATA_PIO)	+= eata_pio.o
 obj-$(CONFIG_SCSI_7000FASST)	+= wd7000.o
-obj-$(CONFIG_SCSI_MCA_53C9X)	+= NCR53C9x.o	mca_53c9x.o
 obj-$(CONFIG_SCSI_IBMMCA)	+= ibmmca.o
 obj-$(CONFIG_SCSI_EATA)		+= eata.o
 obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
@@ -112,13 +104,12 @@
 obj-$(CONFIG_BLK_DEV_IDESCSI)	+= ide-scsi.o
 obj-$(CONFIG_SCSI_MESH)		+= mesh.o
 obj-$(CONFIG_SCSI_MAC53C94)	+= mac53c94.o
-obj-$(CONFIG_SCSI_DECNCR)	+= NCR53C9x.o	dec_esp.o
 obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
 obj-$(CONFIG_SCSI_3W_9XXX)	+= 3w-9xxx.o
 obj-$(CONFIG_SCSI_PPA)		+= ppa.o
 obj-$(CONFIG_SCSI_IMM)		+= imm.o
 obj-$(CONFIG_JAZZ_ESP)		+= esp_scsi.o	jazz_esp.o
-obj-$(CONFIG_SUN3X_ESP)		+= NCR53C9x.o	sun3x_esp.o
+obj-$(CONFIG_SUN3X_ESP)		+= esp_scsi.o	sun3x_esp.o
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
 obj-$(CONFIG_SCSI_SNI_53C710)	+= 53c700.o sni_53c710.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
@@ -138,6 +129,7 @@
 obj-$(CONFIG_BLK_DEV_SR)	+= sr_mod.o
 obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
+obj-$(CONFIG_SCSI_ENCLOSURE)	+= ses.o
 
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
deleted file mode 100644
index 5b0efc9..0000000
--- a/drivers/scsi/NCR53C9x.c
+++ /dev/null
@@ -1,3654 +0,0 @@
-/* NCR53C9x.c:  Generic SCSI driver code for NCR53C9x chips.
- *
- * Originally esp.c : EnhancedScsiProcessor Sun SCSI driver code.
- *
- * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
- *
- * Most DMA dependencies put in driver specific files by 
- * Jesper Skov (jskov@cygnus.co.uk)
- *
- * Set up to use esp_read/esp_write (preprocessor macros in NCR53c9x.h) by
- * Tymm Twillman (tymm@coe.missouri.edu)
- */
-
-/* TODO:
- *
- * 1) Maybe disable parity checking in config register one for SCSI1
- *    targets.  (Gilmore says parity error on the SBus can lock up
- *    old sun4c's)
- * 2) Add support for DMA2 pipelining.
- * 3) Add tagged queueing.
- * 4) Maybe change use of "esp" to something more "NCR"'ish.
- */
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <asm/system.h>
-#include <asm/ptrace.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-/* Command phase enumeration. */
-enum {
-	not_issued    = 0x00,  /* Still in the issue_SC queue.          */
-
-	/* Various forms of selecting a target. */
-#define in_slct_mask    0x10
-	in_slct_norm  = 0x10,  /* ESP is arbitrating, normal selection  */
-	in_slct_stop  = 0x11,  /* ESP will select, then stop with IRQ   */
-	in_slct_msg   = 0x12,  /* select, then send a message           */
-	in_slct_tag   = 0x13,  /* select and send tagged queue msg      */
-	in_slct_sneg  = 0x14,  /* select and acquire sync capabilities  */
-
-	/* Any post selection activity. */
-#define in_phases_mask  0x20
-	in_datain     = 0x20,  /* Data is transferring from the bus     */
-	in_dataout    = 0x21,  /* Data is transferring to the bus       */
-	in_data_done  = 0x22,  /* Last DMA data operation done (maybe)  */
-	in_msgin      = 0x23,  /* Eating message from target            */
-	in_msgincont  = 0x24,  /* Eating more msg bytes from target     */
-	in_msgindone  = 0x25,  /* Decide what to do with what we got    */
-	in_msgout     = 0x26,  /* Sending message to target             */
-	in_msgoutdone = 0x27,  /* Done sending msg out                  */
-	in_cmdbegin   = 0x28,  /* Sending cmd after abnormal selection  */
-	in_cmdend     = 0x29,  /* Done sending slow cmd                 */
-	in_status     = 0x2a,  /* Was in status phase, finishing cmd    */
-	in_freeing    = 0x2b,  /* freeing the bus for cmd cmplt or disc */
-	in_the_dark   = 0x2c,  /* Don't know what bus phase we are in   */
-
-	/* Special states, ie. not normal bus transitions... */
-#define in_spec_mask    0x80
-	in_abortone   = 0x80,  /* Aborting one command currently        */
-	in_abortall   = 0x81,  /* Blowing away all commands we have     */
-	in_resetdev   = 0x82,  /* SCSI target reset in progress         */
-	in_resetbus   = 0x83,  /* SCSI bus reset in progress            */
-	in_tgterror   = 0x84,  /* Target did something stupid           */
-};
-
-enum {
-	/* Zero has special meaning, see skipahead[12]. */
-/*0*/	do_never,
-
-/*1*/	do_phase_determine,
-/*2*/	do_reset_bus,
-/*3*/	do_reset_complete,
-/*4*/	do_work_bus,
-/*5*/	do_intr_end
-};
-
-/* The master ring of all esp hosts we are managing in this driver. */
-static struct NCR_ESP *espchain;
-int nesps = 0, esps_in_use = 0, esps_running = 0;
-EXPORT_SYMBOL(nesps);
-EXPORT_SYMBOL(esps_running);
-
-irqreturn_t esp_intr(int irq, void *dev_id);
-
-/* Debugging routines */
-static struct esp_cmdstrings {
-	unchar cmdchar;
-	char *text;
-} esp_cmd_strings[] = {
-	/* Miscellaneous */
-	{ ESP_CMD_NULL, "ESP_NOP", },
-	{ ESP_CMD_FLUSH, "FIFO_FLUSH", },
-	{ ESP_CMD_RC, "RSTESP", },
-	{ ESP_CMD_RS, "RSTSCSI", },
-	/* Disconnected State Group */
-	{ ESP_CMD_RSEL, "RESLCTSEQ", },
-	{ ESP_CMD_SEL, "SLCTNATN", },
-	{ ESP_CMD_SELA, "SLCTATN", },
-	{ ESP_CMD_SELAS, "SLCTATNSTOP", },
-	{ ESP_CMD_ESEL, "ENSLCTRESEL", },
-	{ ESP_CMD_DSEL, "DISSELRESEL", },
-	{ ESP_CMD_SA3, "SLCTATN3", },
-	{ ESP_CMD_RSEL3, "RESLCTSEQ", },
-	/* Target State Group */
-	{ ESP_CMD_SMSG, "SNDMSG", },
-	{ ESP_CMD_SSTAT, "SNDSTATUS", },
-	{ ESP_CMD_SDATA, "SNDDATA", },
-	{ ESP_CMD_DSEQ, "DISCSEQ", },
-	{ ESP_CMD_TSEQ, "TERMSEQ", },
-	{ ESP_CMD_TCCSEQ, "TRGTCMDCOMPSEQ", },
-	{ ESP_CMD_DCNCT, "DISC", },
-	{ ESP_CMD_RMSG, "RCVMSG", },
-	{ ESP_CMD_RCMD, "RCVCMD", },
-	{ ESP_CMD_RDATA, "RCVDATA", },
-	{ ESP_CMD_RCSEQ, "RCVCMDSEQ", },
-	/* Initiator State Group */
-	{ ESP_CMD_TI, "TRANSINFO", },
-	{ ESP_CMD_ICCSEQ, "INICMDSEQCOMP", },
-	{ ESP_CMD_MOK, "MSGACCEPTED", },
-	{ ESP_CMD_TPAD, "TPAD", },
-	{ ESP_CMD_SATN, "SATN", },
-	{ ESP_CMD_RATN, "RATN", },
-};
-#define NUM_ESP_COMMANDS  ((sizeof(esp_cmd_strings)) / (sizeof(struct esp_cmdstrings)))
-
-/* Print textual representation of an ESP command */
-static inline void esp_print_cmd(unchar espcmd)
-{
-	unchar dma_bit = espcmd & ESP_CMD_DMA;
-	int i;
-
-	espcmd &= ~dma_bit;
-	for(i=0; i<NUM_ESP_COMMANDS; i++)
-		if(esp_cmd_strings[i].cmdchar == espcmd)
-			break;
-	if(i==NUM_ESP_COMMANDS)
-		printk("ESP_Unknown");
-	else
-		printk("%s%s", esp_cmd_strings[i].text,
-		       ((dma_bit) ? "+DMA" : ""));
-}
-
-/* Print the status register's value */
-static inline void esp_print_statreg(unchar statreg)
-{
-	unchar phase;
-
-	printk("STATUS<");
-	phase = statreg & ESP_STAT_PMASK;
-	printk("%s,", (phase == ESP_DOP ? "DATA-OUT" :
-		       (phase == ESP_DIP ? "DATA-IN" :
-			(phase == ESP_CMDP ? "COMMAND" :
-			 (phase == ESP_STATP ? "STATUS" :
-			  (phase == ESP_MOP ? "MSG-OUT" :
-			   (phase == ESP_MIP ? "MSG_IN" :
-			    "unknown")))))));
-	if(statreg & ESP_STAT_TDONE)
-		printk("TRANS_DONE,");
-	if(statreg & ESP_STAT_TCNT)
-		printk("TCOUNT_ZERO,");
-	if(statreg & ESP_STAT_PERR)
-		printk("P_ERROR,");
-	if(statreg & ESP_STAT_SPAM)
-		printk("SPAM,");
-	if(statreg & ESP_STAT_INTR)
-		printk("IRQ,");
-	printk(">");
-}
-
-/* Print the interrupt register's value */
-static inline void esp_print_ireg(unchar intreg)
-{
-	printk("INTREG< ");
-	if(intreg & ESP_INTR_S)
-		printk("SLCT_NATN ");
-	if(intreg & ESP_INTR_SATN)
-		printk("SLCT_ATN ");
-	if(intreg & ESP_INTR_RSEL)
-		printk("RSLCT ");
-	if(intreg & ESP_INTR_FDONE)
-		printk("FDONE ");
-	if(intreg & ESP_INTR_BSERV)
-		printk("BSERV ");
-	if(intreg & ESP_INTR_DC)
-		printk("DISCNCT ");
-	if(intreg & ESP_INTR_IC)
-		printk("ILL_CMD ");
-	if(intreg & ESP_INTR_SR)
-		printk("SCSI_BUS_RESET ");
-	printk(">");
-}
-
-/* Print the sequence step registers contents */
-static inline void esp_print_seqreg(unchar stepreg)
-{
-	stepreg &= ESP_STEP_VBITS;
-	printk("STEP<%s>",
-	       (stepreg == ESP_STEP_ASEL ? "SLCT_ARB_CMPLT" :
-		(stepreg == ESP_STEP_SID ? "1BYTE_MSG_SENT" :
-		 (stepreg == ESP_STEP_NCMD ? "NOT_IN_CMD_PHASE" :
-		  (stepreg == ESP_STEP_PPC ? "CMD_BYTES_LOST" :
-		   (stepreg == ESP_STEP_FINI4 ? "CMD_SENT_OK" :
-		    "UNKNOWN"))))));
-}
-
-static char *phase_string(int phase)
-{
-	switch(phase) {
-	case not_issued:
-		return "UNISSUED";
-	case in_slct_norm:
-		return "SLCTNORM";
-	case in_slct_stop:
-		return "SLCTSTOP";
-	case in_slct_msg:
-		return "SLCTMSG";
-	case in_slct_tag:
-		return "SLCTTAG";
-	case in_slct_sneg:
-		return "SLCTSNEG";
-	case in_datain:
-		return "DATAIN";
-	case in_dataout:
-		return "DATAOUT";
-	case in_data_done:
-		return "DATADONE";
-	case in_msgin:
-		return "MSGIN";
-	case in_msgincont:
-		return "MSGINCONT";
-	case in_msgindone:
-		return "MSGINDONE";
-	case in_msgout:
-		return "MSGOUT";
-	case in_msgoutdone:
-		return "MSGOUTDONE";
-	case in_cmdbegin:
-		return "CMDBEGIN";
-	case in_cmdend:
-		return "CMDEND";
-	case in_status:
-		return "STATUS";
-	case in_freeing:
-		return "FREEING";
-	case in_the_dark:
-		return "CLUELESS";
-	case in_abortone:
-		return "ABORTONE";
-	case in_abortall:
-		return "ABORTALL";
-	case in_resetdev:
-		return "RESETDEV";
-	case in_resetbus:
-		return "RESETBUS";
-	case in_tgterror:
-		return "TGTERROR";
-	default:
-		return "UNKNOWN";
-	};
-}
-
-#ifdef DEBUG_STATE_MACHINE
-static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
-{
-	ESPLOG(("<%s>", phase_string(newphase)));
-	s->SCp.sent_command = s->SCp.phase;
-	s->SCp.phase = newphase;
-}
-#else
-#define esp_advance_phase(__s, __newphase) \
-	(__s)->SCp.sent_command = (__s)->SCp.phase; \
-	(__s)->SCp.phase = (__newphase);
-#endif
-
-#ifdef DEBUG_ESP_CMDS
-static inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
-			   unchar cmd)
-{
-	esp->espcmdlog[esp->espcmdent] = cmd;
-	esp->espcmdent = (esp->espcmdent + 1) & 31;
-	esp_write(eregs->esp_cmnd, cmd);
-}
-#else
-#define esp_cmd(__esp, __eregs, __cmd)	esp_write((__eregs)->esp_cmnd, (__cmd))
-#endif
-
-/* How we use the various Linux SCSI data structures for operation.
- *
- * struct scsi_cmnd:
- *
- *   We keep track of the syncronous capabilities of a target
- *   in the device member, using sync_min_period and
- *   sync_max_offset.  These are the values we directly write
- *   into the ESP registers while running a command.  If offset
- *   is zero the ESP will use asynchronous transfers.
- *   If the borken flag is set we assume we shouldn't even bother
- *   trying to negotiate for synchronous transfer as this target
- *   is really stupid.  If we notice the target is dropping the
- *   bus, and we have been allowing it to disconnect, we clear
- *   the disconnect flag.
- */
-
-/* Manipulation of the ESP command queues.  Thanks to the aha152x driver
- * and its author, Juergen E. Fischer, for the methods used here.
- * Note that these are per-ESP queues, not global queues like
- * the aha152x driver uses.
- */
-static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
-{
-	Scsi_Cmnd *end;
-
-	new_SC->host_scribble = (unsigned char *) NULL;
-	if(!*SC)
-		*SC = new_SC;
-	else {
-		for(end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble)
-			;
-		end->host_scribble = (unsigned char *) new_SC;
-	}
-}
-
-static inline void prepend_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
-{
-	new_SC->host_scribble = (unsigned char *) *SC;
-	*SC = new_SC;
-}
-
-static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
-{
-	Scsi_Cmnd *ptr;
-
-	ptr = *SC;
-	if(ptr)
-		*SC = (Scsi_Cmnd *) (*SC)->host_scribble;
-	return ptr;
-}
-
-static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
-{
-	Scsi_Cmnd *ptr, *prev;
-
-	for(ptr = *SC, prev = NULL;
-	    ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
-	    prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
-		;
-	if(ptr) {
-		if(prev)
-			prev->host_scribble=ptr->host_scribble;
-		else
-			*SC=(Scsi_Cmnd *)ptr->host_scribble;
-	}
-	return ptr;
-}
-
-/* Resetting various pieces of the ESP scsi driver chipset */
-
-/* Reset the ESP chip, _not_ the SCSI bus. */
-static void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	int family_code, version, i;
-	volatile int trash;
-
-	/* Now reset the ESP chip */
-	esp_cmd(esp, eregs, ESP_CMD_RC);
-	esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
-	if(esp->erev == fast)
-		esp_write(eregs->esp_cfg2, ESP_CONFIG2_FENAB);
-	esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
-
-	/* This is the only point at which it is reliable to read
-	 * the ID-code for a fast ESP chip variant.
-	 */
-	esp->max_period = ((35 * esp->ccycle) / 1000);
-	if(esp->erev == fast) {
-		char *erev2string[] = {
-			"Emulex FAS236",
-			"Emulex FPESP100A",
-			"fast",
-			"QLogic FAS366",
-			"Emulex FAS216",
-			"Symbios Logic 53CF9x-2",
-			"unknown!"
-		};
-			
-		version = esp_read(eregs->esp_uid);
-		family_code = (version & 0xf8) >> 3;
-		if(family_code == 0x02) {
-		        if ((version & 7) == 2)
-			        esp->erev = fas216;	
-                        else
-			        esp->erev = fas236;
-		} else if(family_code == 0x0a)
-			esp->erev = fas366; /* Version is usually '5'. */
-		else if(family_code == 0x00) {
-			if ((version & 7) == 2)
-				esp->erev = fas100a; /* NCR53C9X */
-			else
-				esp->erev = espunknown;
-		} else if(family_code == 0x14) {
-			if ((version & 7) == 2)
-				esp->erev = fsc;
-		        else
-				esp->erev = espunknown;
-		} else if(family_code == 0x00) {
-			if ((version & 7) == 2)
-				esp->erev = fas100a; /* NCR53C9X */
-			else
-				esp->erev = espunknown;
-		} else
-			esp->erev = espunknown;
-		ESPLOG(("esp%d: FAST chip is %s (family=%d, version=%d)\n",
-			esp->esp_id, erev2string[esp->erev - fas236],
-			family_code, (version & 7)));
-
-		esp->min_period = ((4 * esp->ccycle) / 1000);
-	} else {
-		esp->min_period = ((5 * esp->ccycle) / 1000);
-	}
-
-	/* Reload the configuration registers */
-	esp_write(eregs->esp_cfact, esp->cfact);
-	esp->prev_stp = 0;
-	esp_write(eregs->esp_stp, 0);
-	esp->prev_soff = 0;
-	esp_write(eregs->esp_soff, 0);
-	esp_write(eregs->esp_timeo, esp->neg_defp);
-	esp->max_period = (esp->max_period + 3)>>2;
-	esp->min_period = (esp->min_period + 3)>>2;
-
-	esp_write(eregs->esp_cfg1, esp->config1);
-	switch(esp->erev) {
-	case esp100:
-		/* nothing to do */
-		break;
-	case esp100a:
-		esp_write(eregs->esp_cfg2, esp->config2);
-		break;
-	case esp236:
-		/* Slow 236 */
-		esp_write(eregs->esp_cfg2, esp->config2);
-		esp->prev_cfg3 = esp->config3[0];
-		esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-		break;
-	case fas366:
-		panic("esp: FAS366 support not present, please notify "
-		      "jongk@cs.utwente.nl");
-		break;
-	case fas216:
-	case fas236:
-	case fsc:
-		/* Fast ESP variants */
-		esp_write(eregs->esp_cfg2, esp->config2);
-		for(i=0; i<8; i++)
-			esp->config3[i] |= ESP_CONFIG3_FCLK;
-		esp->prev_cfg3 = esp->config3[0];
-		esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-		if(esp->diff)
-			esp->radelay = 0;
-		else
-			esp->radelay = 16;
-		/* Different timeout constant for these chips */
-		esp->neg_defp =
-			FSC_NEG_DEFP(esp->cfreq,
-				     (esp->cfact == ESP_CCF_F0 ?
-				      ESP_CCF_F7 + 1 : esp->cfact));
-		esp_write(eregs->esp_timeo, esp->neg_defp);
-		/* Enable Active Negotiation if possible */
-		if((esp->erev == fsc) && !esp->diff)
-			esp_write(eregs->esp_cfg4, ESP_CONFIG4_EAN);
-		break;
-	case fas100a:
-		/* Fast 100a */
-		esp_write(eregs->esp_cfg2, esp->config2);
-		for(i=0; i<8; i++)
-			esp->config3[i] |= ESP_CONFIG3_FCLOCK;
-		esp->prev_cfg3 = esp->config3[0];
-		esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-		esp->radelay = 32;
-		break;
-	default:
-		panic("esp: what could it be... I wonder...");
-		break;
-	};
-
-	/* Eat any bitrot in the chip */
-	trash = esp_read(eregs->esp_intrpt);
-	udelay(100);
-}
-
-/* This places the ESP into a known state at boot time. */
-void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	volatile unchar trash;
-
-	/* Reset the DMA */
-	if(esp->dma_reset)
-		esp->dma_reset(esp);
-
-	/* Reset the ESP */
-	esp_reset_esp(esp, eregs);
-
-	/* Reset the SCSI bus, but tell ESP not to generate an irq */
-	esp_write(eregs->esp_cfg1, (esp_read(eregs->esp_cfg1) | ESP_CONFIG1_SRRDISAB));
-	esp_cmd(esp, eregs, ESP_CMD_RS);
-	udelay(400);
-	esp_write(eregs->esp_cfg1, esp->config1);
-
-	/* Eat any bitrot in the chip and we are done... */
-	trash = esp_read(eregs->esp_intrpt);
-}
-EXPORT_SYMBOL(esp_bootup_reset);
-
-/* Allocate structure and insert basic data such as SCSI chip frequency
- * data and a pointer to the device
- */
-struct NCR_ESP* esp_allocate(struct scsi_host_template *tpnt, void *esp_dev,
-			     int hotplug)
-{
-	struct NCR_ESP *esp, *elink;
-	struct Scsi_Host *esp_host;
-
-	if (hotplug)
-		esp_host = scsi_host_alloc(tpnt, sizeof(struct NCR_ESP));
-	else
-		esp_host = scsi_register(tpnt, sizeof(struct NCR_ESP));
-	if(!esp_host)
-		panic("Cannot register ESP SCSI host");
-	esp = (struct NCR_ESP *) esp_host->hostdata;
-	if(!esp)
-		panic("No esp in hostdata");
-	esp->ehost = esp_host;
-	esp->edev = esp_dev;
-	esp->esp_id = nesps++;
-
-	/* Set bitshift value (only used on Amiga with multiple ESPs) */
-	esp->shift = 2;
-
-	/* Put into the chain of esp chips detected */
-	if(espchain) {
-		elink = espchain;
-		while(elink->next) elink = elink->next;
-		elink->next = esp;
-	} else {
-		espchain = esp;
-	}
-	esp->next = NULL;
-
-	return esp;
-}
-
-void esp_deallocate(struct NCR_ESP *esp)
-{
-	struct NCR_ESP *elink;
-
-	if(espchain == esp) {
-		espchain = NULL;
-	} else {
-		for(elink = espchain; elink && (elink->next != esp); elink = elink->next);
-		if(elink) 
-			elink->next = esp->next;
-	}
-	nesps--;
-}
-
-/* Complete initialization of ESP structure and device
- * Caller must have initialized appropriate parts of the ESP structure
- * between the call to esp_allocate and this function.
- */
-void esp_initialize(struct NCR_ESP *esp)
-{
-	struct ESP_regs *eregs = esp->eregs;
-	unsigned int fmhz;
-	unchar ccf;
-	int i;
-	
-	/* Check out the clock properties of the chip. */
-
-	/* This is getting messy but it has to be done
-	 * correctly or else you get weird behavior all
-	 * over the place.  We are trying to basically
-	 * figure out three pieces of information.
-	 *
-	 * a) Clock Conversion Factor
-	 *
-	 *    This is a representation of the input
-	 *    crystal clock frequency going into the
-	 *    ESP on this machine.  Any operation whose
-	 *    timing is longer than 400ns depends on this
-	 *    value being correct.  For example, you'll
-	 *    get blips for arbitration/selection during
-	 *    high load or with multiple targets if this
-	 *    is not set correctly.
-	 *
-	 * b) Selection Time-Out
-	 *
-	 *    The ESP isn't very bright and will arbitrate
-	 *    for the bus and try to select a target
-	 *    forever if you let it.  This value tells
-	 *    the ESP when it has taken too long to
-	 *    negotiate and that it should interrupt
-	 *    the CPU so we can see what happened.
-	 *    The value is computed as follows (from
-	 *    NCR/Symbios chip docs).
-	 *
-	 *          (Time Out Period) *  (Input Clock)
-	 *    STO = ----------------------------------
-	 *          (8192) * (Clock Conversion Factor)
-	 *
-	 *    You usually want the time out period to be
-	 *    around 250ms, I think we'll set it a little
-	 *    bit higher to account for fully loaded SCSI
-	 *    bus's and slow devices that don't respond so
-	 *    quickly to selection attempts. (yeah, I know
-	 *    this is out of spec. but there is a lot of
-	 *    buggy pieces of firmware out there so bite me)
-	 *
-	 * c) Imperical constants for synchronous offset
-	 *    and transfer period register values
-	 *
-	 *    This entails the smallest and largest sync
-	 *    period we could ever handle on this ESP.
-	 */
-	
-	fmhz = esp->cfreq;
-
-	if(fmhz <= (5000000))
-		ccf = 0;
-	else
-		ccf = (((5000000 - 1) + (fmhz))/(5000000));
-	if(!ccf || ccf > 8) {
-		/* If we can't find anything reasonable,
-		 * just assume 20MHZ.  This is the clock
-		 * frequency of the older sun4c's where I've
-		 * been unable to find the clock-frequency
-		 * PROM property.  All other machines provide
-		 * useful values it seems.
-		 */
-		ccf = ESP_CCF_F4;
-		fmhz = (20000000);
-	}
-	if(ccf==(ESP_CCF_F7+1))
-		esp->cfact = ESP_CCF_F0;
-	else if(ccf == ESP_CCF_NEVER)
-		esp->cfact = ESP_CCF_F2;
-	else
-		esp->cfact = ccf;
-	esp->cfreq = fmhz;
-	esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
-	esp->ctick = ESP_TICK(ccf, esp->ccycle);
-	esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
-	esp->sync_defp = SYNC_DEFP_SLOW;
-
-	printk("SCSI ID %d Clk %dMHz CCF=%d TOut %d ",
-	       esp->scsi_id, (esp->cfreq / 1000000),
-	       ccf, (int) esp->neg_defp);
-
-	/* Fill in ehost data */
-	esp->ehost->base = (unsigned long)eregs;
-	esp->ehost->this_id = esp->scsi_id;
-	esp->ehost->irq = esp->irq;
-
-	/* SCSI id mask */
-	esp->scsi_id_mask = (1 << esp->scsi_id);
-
-	/* Probe the revision of this esp */
-	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
-	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
-	esp_write(eregs->esp_cfg2, esp->config2);
-	if((esp_read(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=
-	   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
-		printk("NCR53C90(esp100)\n");
-		esp->erev = esp100;
-	} else {
-		esp->config2 = 0;
-		esp_write(eregs->esp_cfg2, 0);
-		esp_write(eregs->esp_cfg3, 5);
-		if(esp_read(eregs->esp_cfg3) != 5) {
-			printk("NCR53C90A(esp100a)\n");
-			esp->erev = esp100a;
-		} else {
-			int target;
-
-			for(target=0; target<8; target++)
-				esp->config3[target] = 0;
-			esp->prev_cfg3 = 0;
-			esp_write(eregs->esp_cfg3, 0);
-			if(ccf > ESP_CCF_F5) {
-				printk("NCR53C9XF(espfast)\n");
-				esp->erev = fast;
-				esp->sync_defp = SYNC_DEFP_FAST;
-			} else {
-				printk("NCR53C9x(esp236)\n");
-				esp->erev = esp236;
-			}
-		}
-	}				
-
-	/* Initialize the command queues */
-	esp->current_SC = NULL;
-	esp->disconnected_SC = NULL;
-	esp->issue_SC = NULL;
-
-	/* Clear the state machines. */
-	esp->targets_present = 0;
-	esp->resetting_bus = 0;
-	esp->snip = 0;
-
-	init_waitqueue_head(&esp->reset_queue);
-
-	esp->fas_premature_intr_workaround = 0;
-	for(i = 0; i < 32; i++)
-		esp->espcmdlog[i] = 0;
-	esp->espcmdent = 0;
-	for(i = 0; i < 16; i++) {
-		esp->cur_msgout[i] = 0;
-		esp->cur_msgin[i] = 0;
-	}
-	esp->prevmsgout = esp->prevmsgin = 0;
-	esp->msgout_len = esp->msgin_len = 0;
-
-	/* Clear the one behind caches to hold unmatchable values. */
-	esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff;
-
-	/* Reset the thing before we try anything... */
-	esp_bootup_reset(esp, eregs);
-
-	esps_in_use++;
-}
-
-/* The info function will return whatever useful
- * information the developer sees fit.  If not provided, then
- * the name field will be used instead.
- */
-const char *esp_info(struct Scsi_Host *host)
-{
-	struct NCR_ESP *esp;
-
-	esp = (struct NCR_ESP *) host->hostdata;
-	switch(esp->erev) {
-	case esp100:
-		return "ESP100 (NCR53C90)";
-	case esp100a:
-		return "ESP100A (NCR53C90A)";
-	case esp236:
-		return "ESP236 (NCR53C9x)";
-	case fas216:
-		return "Emulex FAS216";
-	case fas236:
-		return "Emulex FAS236";
-	case fas366:
-		return "QLogic FAS366";
-	case fas100a:
-		return "FPESP100A";
-	case fsc:
-		return "Symbios Logic 53CF9x-2";
-	default:
-		panic("Bogon ESP revision");
-	};
-}
-EXPORT_SYMBOL(esp_info);
-
-/* From Wolfgang Stanglmeier's NCR scsi driver. */
-struct info_str
-{
-	char *buffer;
-	int length;
-	int offset;
-	int pos;
-};
-
-static void copy_mem_info(struct info_str *info, char *data, int len)
-{
-	if (info->pos + len > info->length)
-		len = info->length - info->pos;
-
-	if (info->pos + len < info->offset) {
-		info->pos += len;
-		return;
-	}
-	if (info->pos < info->offset) {
-		data += (info->offset - info->pos);
-		len  -= (info->offset - info->pos);
-	}
-
-	if (len > 0) {
-		memcpy(info->buffer + info->pos, data, len);
-		info->pos += len;
-	}
-}
-
-static int copy_info(struct info_str *info, char *fmt, ...)
-{
-	va_list args;
-	char buf[81];
-	int len;
-
-	va_start(args, fmt);
-	len = vsprintf(buf, fmt, args);
-	va_end(args);
-
-	copy_mem_info(info, buf, len);
-	return len;
-}
-
-static int esp_host_info(struct NCR_ESP *esp, char *ptr, off_t offset, int len)
-{
-	struct scsi_device *sdev;
-	struct info_str info;
-	int i;
-
-	info.buffer	= ptr;
-	info.length	= len;
-	info.offset	= offset;
-	info.pos	= 0;
-
-	copy_info(&info, "ESP Host Adapter:\n");
-	copy_info(&info, "\tESP Model\t\t");
-	switch(esp->erev) {
-	case esp100:
-		copy_info(&info, "ESP100 (NCR53C90)\n");
-		break;
-	case esp100a:
-		copy_info(&info, "ESP100A (NCR53C90A)\n");
-		break;
-	case esp236:
-		copy_info(&info, "ESP236 (NCR53C9x)\n");
-		break;
-	case fas216:
-		copy_info(&info, "Emulex FAS216\n");
-		break;
-	case fas236:
-		copy_info(&info, "Emulex FAS236\n");
-		break;
-	case fas100a:
-		copy_info(&info, "FPESP100A\n");
-		break;
-	case fast:
-		copy_info(&info, "Generic FAST\n");
-		break;
-	case fas366:
-		copy_info(&info, "QLogic FAS366\n");
-		break;
-	case fsc:
-		copy_info(&info, "Symbios Logic 53C9x-2\n");
-		break;
-	case espunknown:
-	default:
-		copy_info(&info, "Unknown!\n");
-		break;
-	};
-	copy_info(&info, "\tLive Targets\t\t[ ");
-	for(i = 0; i < 15; i++) {
-		if(esp->targets_present & (1 << i))
-			copy_info(&info, "%d ", i);
-	}
-	copy_info(&info, "]\n\n");
-	
-	/* Now describe the state of each existing target. */
-	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\n");
-
-	shost_for_each_device(sdev, esp->ehost) {
-		struct esp_device *esp_dev = sdev->hostdata;
-		uint id = sdev->id;
-
-		if (!(esp->targets_present & (1 << id)))
-			continue;
-
-		copy_info(&info, "%d\t\t", id);
-		copy_info(&info, "%08lx\t", esp->config3[id]);
-		copy_info(&info, "[%02lx,%02lx]\t\t\t",
-			esp_dev->sync_max_offset,
-			esp_dev->sync_min_period);
-		copy_info(&info, "%s\n", esp_dev->disconnect ? "yes" : "no");
-	}
-
-	return info.pos > info.offset? info.pos - info.offset : 0;
-}
-
-/* ESP proc filesystem code. */
-int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length,
-		  int inout)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *)shost->hostdata;
-
-	if(inout)
-		return -EINVAL; /* not yet */
-	if(start)
-		*start = buffer;
-	return esp_host_info(esp, buffer, offset, length);
-}
-EXPORT_SYMBOL(esp_proc_info);
-
-static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	if(sp->use_sg == 0) {
-		sp->SCp.this_residual = sp->request_bufflen;
-		sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
-		sp->SCp.buffers_residual = 0;
-		if (esp->dma_mmu_get_scsi_one)
-			esp->dma_mmu_get_scsi_one(esp, sp);
-		else
-			sp->SCp.ptr =
-				(char *) virt_to_phys(sp->request_buffer);
-	} else {
-		sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
-		sp->SCp.buffers_residual = sp->use_sg - 1;
-		sp->SCp.this_residual = sp->SCp.buffer->length;
-		if (esp->dma_mmu_get_scsi_sgl)
-			esp->dma_mmu_get_scsi_sgl(esp, sp);
-		else
-			sp->SCp.ptr =
-				(char *) virt_to_phys(sg_virt(sp->SCp.buffer));
-	}
-}
-
-static void esp_release_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	if(sp->use_sg == 0) {
-		if (esp->dma_mmu_release_scsi_one)
-			esp->dma_mmu_release_scsi_one(esp, sp);
-	} else {
-		if (esp->dma_mmu_release_scsi_sgl)
-			esp->dma_mmu_release_scsi_sgl(esp, sp);
-	}
-}
-
-static void esp_restore_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	struct esp_pointers *ep = &esp->data_pointers[scmd_id(sp)];
-
-	sp->SCp.ptr = ep->saved_ptr;
-	sp->SCp.buffer = ep->saved_buffer;
-	sp->SCp.this_residual = ep->saved_this_residual;
-	sp->SCp.buffers_residual = ep->saved_buffers_residual;
-}
-
-static void esp_save_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	struct esp_pointers *ep = &esp->data_pointers[scmd_id(sp)];
-
-	ep->saved_ptr = sp->SCp.ptr;
-	ep->saved_buffer = sp->SCp.buffer;
-	ep->saved_this_residual = sp->SCp.this_residual;
-	ep->saved_buffers_residual = sp->SCp.buffers_residual;
-}
-
-/* Some rules:
- *
- *   1) Never ever panic while something is live on the bus.
- *      If there is to be any chance of syncing the disks this
- *      rule is to be obeyed.
- *
- *   2) Any target that causes a foul condition will no longer
- *      have synchronous transfers done to it, no questions
- *      asked.
- *
- *   3) Keep register accesses to a minimum.  Think about some
- *      day when we have Xbus machines this is running on and
- *      the ESP chip is on the other end of the machine on a
- *      different board from the cpu where this is running.
- */
-
-/* Fire off a command.  We assume the bus is free and that the only
- * case where we could see an interrupt is where we have disconnected
- * commands active and they are trying to reselect us.
- */
-static inline void esp_check_cmd(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	switch(sp->cmd_len) {
-	case 6:
-	case 10:
-	case 12:
-		esp->esp_slowcmd = 0;
-		break;
-
-	default:
-		esp->esp_slowcmd = 1;
-		esp->esp_scmdleft = sp->cmd_len;
-		esp->esp_scmdp = &sp->cmnd[0];
-		break;
-	};
-}
-
-static inline void build_sync_nego_msg(struct NCR_ESP *esp, int period, int offset)
-{
-	esp->cur_msgout[0] = EXTENDED_MESSAGE;
-	esp->cur_msgout[1] = 3;
-	esp->cur_msgout[2] = EXTENDED_SDTR;
-	esp->cur_msgout[3] = period;
-	esp->cur_msgout[4] = offset;
-	esp->msgout_len = 5;
-}
-
-static void esp_exec_cmd(struct NCR_ESP *esp)
-{
-	struct ESP_regs *eregs = esp->eregs;
-	struct esp_device *esp_dev;
-	Scsi_Cmnd *SCptr;
-	struct scsi_device *SDptr;
-	volatile unchar *cmdp = esp->esp_command;
-	unsigned char the_esp_command;
-	int lun, target;
-	int i;
-
-	/* Hold off if we have disconnected commands and
-	 * an IRQ is showing...
-	 */
-	if(esp->disconnected_SC && esp->dma_irq_p(esp))
-		return;
-
-	/* Grab first member of the issue queue. */
-	SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC);
-
-	/* Safe to panic here because current_SC is null. */
-	if(!SCptr)
-		panic("esp: esp_exec_cmd and issue queue is NULL");
-
-	SDptr = SCptr->device;
-	esp_dev = SDptr->hostdata;
-	lun = SCptr->device->lun;
-	target = SCptr->device->id;
-
-	esp->snip = 0;
-	esp->msgout_len = 0;
-
-	/* Send it out whole, or piece by piece?   The ESP
-	 * only knows how to automatically send out 6, 10,
-	 * and 12 byte commands.  I used to think that the
-	 * Linux SCSI code would never throw anything other
-	 * than that to us, but then again there is the
-	 * SCSI generic driver which can send us anything.
-	 */
-	esp_check_cmd(esp, SCptr);
-
-	/* If arbitration/selection is successful, the ESP will leave
-	 * ATN asserted, causing the target to go into message out
-	 * phase.  The ESP will feed the target the identify and then
-	 * the target can only legally go to one of command,
-	 * datain/out, status, or message in phase, or stay in message
-	 * out phase (should we be trying to send a sync negotiation
-	 * message after the identify).  It is not allowed to drop
-	 * BSY, but some buggy targets do and we check for this
-	 * condition in the selection complete code.  Most of the time
-	 * we'll make the command bytes available to the ESP and it
-	 * will not interrupt us until it finishes command phase, we
-	 * cannot do this for command sizes the ESP does not
-	 * understand and in this case we'll get interrupted right
-	 * when the target goes into command phase.
-	 *
-	 * It is absolutely _illegal_ in the presence of SCSI-2 devices
-	 * to use the ESP select w/o ATN command.  When SCSI-2 devices are
-	 * present on the bus we _must_ always go straight to message out
-	 * phase with an identify message for the target.  Being that
-	 * selection attempts in SCSI-1 w/o ATN was an option, doing SCSI-2
-	 * selections should not confuse SCSI-1 we hope.
-	 */
-
-	if(esp_dev->sync) {
-		/* this targets sync is known */
-#ifdef CONFIG_SCSI_MAC_ESP
-do_sync_known:
-#endif
-		if(esp_dev->disconnect)
-			*cmdp++ = IDENTIFY(1, lun);
-		else
-			*cmdp++ = IDENTIFY(0, lun);
-
-		if(esp->esp_slowcmd) {
-			the_esp_command = (ESP_CMD_SELAS | ESP_CMD_DMA);
-			esp_advance_phase(SCptr, in_slct_stop);
-		} else {
-			the_esp_command = (ESP_CMD_SELA | ESP_CMD_DMA);
-			esp_advance_phase(SCptr, in_slct_norm);
-		}
-	} else if(!(esp->targets_present & (1<<target)) || !(esp_dev->disconnect)) {
-		/* After the bootup SCSI code sends both the
-		 * TEST_UNIT_READY and INQUIRY commands we want
-		 * to at least attempt allowing the device to
-		 * disconnect.
-		 */
-		ESPMISC(("esp: Selecting device for first time. target=%d "
-			 "lun=%d\n", target, SCptr->device->lun));
-		if(!SDptr->borken && !esp_dev->disconnect)
-			esp_dev->disconnect = 1;
-
-		*cmdp++ = IDENTIFY(0, lun);
-		esp->prevmsgout = NOP;
-		esp_advance_phase(SCptr, in_slct_norm);
-		the_esp_command = (ESP_CMD_SELA | ESP_CMD_DMA);
-
-		/* Take no chances... */
-		esp_dev->sync_max_offset = 0;
-		esp_dev->sync_min_period = 0;
-	} else {
-		int toshiba_cdrom_hwbug_wkaround = 0;
-
-#ifdef CONFIG_SCSI_MAC_ESP
-		/* Never allow synchronous transfers (disconnect OK) on
-		 * Macintosh. Well, maybe later when we figured out how to 
-		 * do DMA on the machines that support it ...
-		 */
-		esp_dev->disconnect = 1;
-		esp_dev->sync_max_offset = 0;
-		esp_dev->sync_min_period = 0;
-		esp_dev->sync = 1;
-		esp->snip = 0;
-		goto do_sync_known;
-#endif
-		/* We've talked to this guy before,
-		 * but never negotiated.  Let's try
-		 * sync negotiation.
-		 */
-		if(!SDptr->borken) {
-			if((SDptr->type == TYPE_ROM) &&
-			   (!strncmp(SDptr->vendor, "TOSHIBA", 7))) {
-				/* Nice try sucker... */
-				ESPMISC(("esp%d: Disabling sync for buggy "
-					 "Toshiba CDROM.\n", esp->esp_id));
-				toshiba_cdrom_hwbug_wkaround = 1;
-				build_sync_nego_msg(esp, 0, 0);
-			} else {
-				build_sync_nego_msg(esp, esp->sync_defp, 15);
-			}
-		} else {
-			build_sync_nego_msg(esp, 0, 0);
-		}
-		esp_dev->sync = 1;
-		esp->snip = 1;
-
-		/* A fix for broken SCSI1 targets, when they disconnect
-		 * they lock up the bus and confuse ESP.  So disallow
-		 * disconnects for SCSI1 targets for now until we
-		 * find a better fix.
-		 *
-		 * Addendum: This is funny, I figured out what was going
-		 *           on.  The blotzed SCSI1 target would disconnect,
-		 *           one of the other SCSI2 targets or both would be
-		 *           disconnected as well.  The SCSI1 target would
-		 *           stay disconnected long enough that we start
-		 *           up a command on one of the SCSI2 targets.  As
-		 *           the ESP is arbitrating for the bus the SCSI1
-		 *           target begins to arbitrate as well to reselect
-		 *           the ESP.  The SCSI1 target refuses to drop it's
-		 *           ID bit on the data bus even though the ESP is
-		 *           at ID 7 and is the obvious winner for any
-		 *           arbitration.  The ESP is a poor sport and refuses
-		 *           to lose arbitration, it will continue indefinitely
-		 *           trying to arbitrate for the bus and can only be
-		 *           stopped via a chip reset or SCSI bus reset.
-		 *           Therefore _no_ disconnects for SCSI1 targets
-		 *           thank you very much. ;-)
-		 */
-		if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) ||
-		   toshiba_cdrom_hwbug_wkaround || SDptr->borken) {
-			ESPMISC((KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
-				 "lun %d\n", esp->esp_id, SCptr->device->id, SCptr->device->lun));
-			esp_dev->disconnect = 0;
-			*cmdp++ = IDENTIFY(0, lun);
-		} else {
-			*cmdp++ = IDENTIFY(1, lun);
-		}
-
-		/* ESP fifo is only so big...
-		 * Make this look like a slow command.
-		 */
-		esp->esp_slowcmd = 1;
-		esp->esp_scmdleft = SCptr->cmd_len;
-		esp->esp_scmdp = &SCptr->cmnd[0];
-
-		the_esp_command = (ESP_CMD_SELAS | ESP_CMD_DMA);
-		esp_advance_phase(SCptr, in_slct_msg);
-	}
-
-	if(!esp->esp_slowcmd)
-		for(i = 0; i < SCptr->cmd_len; i++)
-			*cmdp++ = SCptr->cmnd[i];
-
-	esp_write(eregs->esp_busid, (target & 7));
-	if (esp->prev_soff != esp_dev->sync_max_offset ||
-	    esp->prev_stp  != esp_dev->sync_min_period ||
-	    (esp->erev > esp100a &&
-	     esp->prev_cfg3 != esp->config3[target])) {
-		esp->prev_soff = esp_dev->sync_max_offset;
-		esp_write(eregs->esp_soff, esp->prev_soff);
-		esp->prev_stp = esp_dev->sync_min_period;
-		esp_write(eregs->esp_stp, esp->prev_stp); 
-		if(esp->erev > esp100a) {
-			esp->prev_cfg3 = esp->config3[target];
-			esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-		}
-	}
-	i = (cmdp - esp->esp_command);
-
-	/* Set up the DMA and ESP counters */
-	if(esp->do_pio_cmds){
-		int j = 0;
-
-		/* 
-		 * XXX MSch:
-		 *
-		 * It seems this is required, at least to clean up
-		 * after failed commands when using PIO mode ...
-		 */
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-
-		for(;j<i;j++)
-			esp_write(eregs->esp_fdata, esp->esp_command[j]);
-		the_esp_command &= ~ESP_CMD_DMA;
-
-		/* Tell ESP to "go". */
-		esp_cmd(esp, eregs, the_esp_command);
-	} else {
-		/* Set up the ESP counters */
-		esp_write(eregs->esp_tclow, i);
-		esp_write(eregs->esp_tcmed, 0);
-		esp->dma_init_write(esp, esp->esp_command_dvma, i);
-
-		/* Tell ESP to "go". */
-		esp_cmd(esp, eregs, the_esp_command);
-	}
-}
-
-/* Queue a SCSI command delivered from the mid-level Linux SCSI code. */
-int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
-{
-	struct NCR_ESP *esp;
-
-	/* Set up func ptr and initial driver cmd-phase. */
-	SCpnt->scsi_done = done;
-	SCpnt->SCp.phase = not_issued;
-
-	esp = (struct NCR_ESP *) SCpnt->device->host->hostdata;
-
-	if(esp->dma_led_on)
-		esp->dma_led_on(esp);
-
-	/* We use the scratch area. */
-	ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->device->id, SCpnt->lun));
-	ESPDISC(("N<%02x,%02x>", SCpnt->device->id, SCpnt->lun));
-
-	esp_get_dmabufs(esp, SCpnt);
-	esp_save_pointers(esp, SCpnt); /* FIXME for tag queueing */
-
-	SCpnt->SCp.Status           = CHECK_CONDITION;
-	SCpnt->SCp.Message          = 0xff;
-	SCpnt->SCp.sent_command     = 0;
-
-	/* Place into our queue. */
-	if(SCpnt->cmnd[0] == REQUEST_SENSE) {
-		ESPQUEUE(("RQSENSE\n"));
-		prepend_SC(&esp->issue_SC, SCpnt);
-	} else {
-		ESPQUEUE(("\n"));
-		append_SC(&esp->issue_SC, SCpnt);
-	}
-
-	/* Run it now if we can. */
-	if(!esp->current_SC && !esp->resetting_bus)
-		esp_exec_cmd(esp);
-
-	return 0;
-}
-
-/* Dump driver state. */
-static void esp_dump_cmd(Scsi_Cmnd *SCptr)
-{
-	ESPLOG(("[tgt<%02x> lun<%02x> "
-		"pphase<%s> cphase<%s>]",
-		SCptr->device->id, SCptr->device->lun,
-		phase_string(SCptr->SCp.sent_command),
-		phase_string(SCptr->SCp.phase)));
-}
-
-static void esp_dump_state(struct NCR_ESP *esp, 
-			   struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-#ifdef DEBUG_ESP_CMDS
-	int i;
-#endif
-
-	ESPLOG(("esp%d: dumping state\n", esp->esp_id));
-	
-	/* Print DMA status */
-	esp->dma_dump_state(esp);
-
-	ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
-		esp->esp_id, esp->sreg, esp->seqreg, esp->ireg));
-	ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
-		esp->esp_id, esp_read(eregs->esp_status), esp_read(eregs->esp_sstep),
-		esp_read(eregs->esp_intrpt)));
-#ifdef DEBUG_ESP_CMDS
-	printk("esp%d: last ESP cmds [", esp->esp_id);
-	i = (esp->espcmdent - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
-	i = (i - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
-	i = (i - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
-	i = (i - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
-	printk("]\n");
-#endif /* (DEBUG_ESP_CMDS) */
-
-	if(SCptr) {
-		ESPLOG(("esp%d: current command ", esp->esp_id));
-		esp_dump_cmd(SCptr);
-	}
-	ESPLOG(("\n"));
-	SCptr = esp->disconnected_SC;
-	ESPLOG(("esp%d: disconnected ", esp->esp_id));
-	while(SCptr) {
-		esp_dump_cmd(SCptr);
-		SCptr = (Scsi_Cmnd *) SCptr->host_scribble;
-	}
-	ESPLOG(("\n"));
-}
-
-/* Abort a command.  The host_lock is acquired by caller. */
-int esp_abort(Scsi_Cmnd *SCptr)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;
-	struct ESP_regs *eregs = esp->eregs;
-	int don;
-
-	ESPLOG(("esp%d: Aborting command\n", esp->esp_id));
-	esp_dump_state(esp, eregs);
-
-	/* Wheee, if this is the current command on the bus, the
-	 * best we can do is assert ATN and wait for msgout phase.
-	 * This should even fix a hung SCSI bus when we lose state
-	 * in the driver and timeout because the eventual phase change
-	 * will cause the ESP to (eventually) give an interrupt.
-	 */
-	if(esp->current_SC == SCptr) {
-		esp->cur_msgout[0] = ABORT;
-		esp->msgout_len = 1;
-		esp->msgout_ctr = 0;
-		esp_cmd(esp, eregs, ESP_CMD_SATN);
-		return SUCCESS;
-	}
-
-	/* If it is still in the issue queue then we can safely
-	 * call the completion routine and report abort success.
-	 */
-	don = esp->dma_ports_p(esp);
-	if(don) {
-		esp->dma_ints_off(esp);
-		synchronize_irq(esp->irq);
-	}
-	if(esp->issue_SC) {
-		Scsi_Cmnd **prev, *this;
-		for(prev = (&esp->issue_SC), this = esp->issue_SC;
-		    this;
-		    prev = (Scsi_Cmnd **) &(this->host_scribble),
-		    this = (Scsi_Cmnd *) this->host_scribble) {
-			if(this == SCptr) {
-				*prev = (Scsi_Cmnd *) this->host_scribble;
-				this->host_scribble = NULL;
-				esp_release_dmabufs(esp, this);
-				this->result = DID_ABORT << 16;
-				this->scsi_done(this);
-				if(don)
-					esp->dma_ints_on(esp);
-				return SUCCESS;
-			}
-		}
-	}
-
-	/* Yuck, the command to abort is disconnected, it is not
-	 * worth trying to abort it now if something else is live
-	 * on the bus at this time.  So, we let the SCSI code wait
-	 * a little bit and try again later.
-	 */
-	if(esp->current_SC) {
-		if(don)
-			esp->dma_ints_on(esp);
-		return FAILED;
-	}
-
-	/* It's disconnected, we have to reconnect to re-establish
-	 * the nexus and tell the device to abort.  However, we really
-	 * cannot 'reconnect' per se.  Don't try to be fancy, just
-	 * indicate failure, which causes our caller to reset the whole
-	 * bus.
-	 */
-
-	if(don)
-		esp->dma_ints_on(esp);
-	return FAILED;
-}
-
-/* We've sent ESP_CMD_RS to the ESP, the interrupt had just
- * arrived indicating the end of the SCSI bus reset.  Our job
- * is to clean out the command queues and begin re-execution
- * of SCSI commands once more.
- */
-static int esp_finish_reset(struct NCR_ESP *esp,
-			    struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *sp = esp->current_SC;
-
-	/* Clean up currently executing command, if any. */
-	if (sp != NULL) {
-		esp_release_dmabufs(esp, sp);
-		sp->result = (DID_RESET << 16);
-		sp->scsi_done(sp);
-		esp->current_SC = NULL;
-	}
-
-	/* Clean up disconnected queue, they have been invalidated
-	 * by the bus reset.
-	 */
-	if (esp->disconnected_SC) {
-		while((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) {
-			esp_release_dmabufs(esp, sp);
-			sp->result = (DID_RESET << 16);
-			sp->scsi_done(sp);
-		}
-	}
-
-	/* SCSI bus reset is complete. */
-	esp->resetting_bus = 0;
-	wake_up(&esp->reset_queue);
-
-	/* Ok, now it is safe to get commands going once more. */
-	if(esp->issue_SC)
-		esp_exec_cmd(esp);
-
-	return do_intr_end;
-}
-
-static int esp_do_resetbus(struct NCR_ESP *esp,
-			   struct ESP_regs *eregs)
-{
-	ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
-	esp->resetting_bus = 1;
-	esp_cmd(esp, eregs, ESP_CMD_RS);
-
-	return do_intr_end;
-}
-
-/* Reset ESP chip, reset hanging bus, then kill active and
- * disconnected commands for targets without soft reset.
- *
- * The host_lock is acquired by caller.
- */
-int esp_reset(Scsi_Cmnd *SCptr)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;
-
-	spin_lock_irq(esp->ehost->host_lock);
-	(void) esp_do_resetbus(esp, esp->eregs);
-	spin_unlock_irq(esp->ehost->host_lock);
-
-	wait_event(esp->reset_queue, (esp->resetting_bus == 0));
-
-	return SUCCESS;
-}
-
-/* Internal ESP done function. */
-static void esp_done(struct NCR_ESP *esp, int error)
-{
-	Scsi_Cmnd *done_SC;
-
-	if(esp->current_SC) {
-		done_SC = esp->current_SC;
-		esp->current_SC = NULL;
-		esp_release_dmabufs(esp, done_SC);
-		done_SC->result = error;
-		done_SC->scsi_done(done_SC);
-
-		/* Bus is free, issue any commands in the queue. */
-		if(esp->issue_SC && !esp->current_SC)
-			esp_exec_cmd(esp);
-	} else {
-		/* Panic is safe as current_SC is null so we may still
-		 * be able to accept more commands to sync disk buffers.
-		 */
-		ESPLOG(("panicing\n"));
-		panic("esp: done() called with NULL esp->current_SC");
-	}
-}
-
-/* Wheee, ESP interrupt engine. */  
-
-/* Forward declarations. */
-static int esp_do_phase_determine(struct NCR_ESP *esp, 
-				  struct ESP_regs *eregs);
-static int esp_do_data_finale(struct NCR_ESP *esp, struct ESP_regs *eregs);
-static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_status(struct NCR_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_cmdbegin(struct NCR_ESP *esp, struct ESP_regs *eregs);
-
-#define sreg_datainp(__sreg)  (((__sreg) & ESP_STAT_PMASK) == ESP_DIP)
-#define sreg_dataoutp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DOP)
-
-/* We try to avoid some interrupts by jumping ahead and see if the ESP
- * has gotten far enough yet.  Hence the following.
- */
-static inline int skipahead1(struct NCR_ESP *esp, struct ESP_regs *eregs,
-			     Scsi_Cmnd *scp, int prev_phase, int new_phase)
-{
-	if(scp->SCp.sent_command != prev_phase)
-		return 0;
-
-	if(esp->dma_irq_p(esp)) {
-		/* Yes, we are able to save an interrupt. */
-		esp->sreg = (esp_read(eregs->esp_status) & ~(ESP_STAT_INTR));
-		esp->ireg = esp_read(eregs->esp_intrpt);
-		if(!(esp->ireg & ESP_INTR_SR))
-			return 0;
-		else
-			return do_reset_complete;
-	}
-	/* Ho hum, target is taking forever... */
-	scp->SCp.sent_command = new_phase; /* so we don't recurse... */
-	return do_intr_end;
-}
-
-static inline int skipahead2(struct NCR_ESP *esp,
-			     struct ESP_regs *eregs,
-			     Scsi_Cmnd *scp, int prev_phase1, int prev_phase2,
-			     int new_phase)
-{
-	if(scp->SCp.sent_command != prev_phase1 &&
-	   scp->SCp.sent_command != prev_phase2)
-		return 0;
-	if(esp->dma_irq_p(esp)) {
-		/* Yes, we are able to save an interrupt. */
-		esp->sreg = (esp_read(eregs->esp_status) & ~(ESP_STAT_INTR));
-		esp->ireg = esp_read(eregs->esp_intrpt);
-		if(!(esp->ireg & ESP_INTR_SR))
-			return 0;
-		else
-			return do_reset_complete;
-	}
-	/* Ho hum, target is taking forever... */
-	scp->SCp.sent_command = new_phase; /* so we don't recurse... */
-	return do_intr_end;
-}
-
-/* Misc. esp helper macros. */
-#define esp_setcount(__eregs, __cnt) \
-	esp_write((__eregs)->esp_tclow, ((__cnt) & 0xff)); \
-	esp_write((__eregs)->esp_tcmed, (((__cnt) >> 8) & 0xff))
-
-#define esp_getcount(__eregs) \
-	((esp_read((__eregs)->esp_tclow)&0xff) | \
-	 ((esp_read((__eregs)->esp_tcmed)&0xff) << 8))
-
-#define fcount(__esp, __eregs) \
-	(esp_read((__eregs)->esp_fflags) & ESP_FF_FBYTES)
-
-#define fnzero(__esp, __eregs) \
-	(esp_read((__eregs)->esp_fflags) & ESP_FF_ONOTZERO)
-
-/* XXX speculative nops unnecessary when continuing amidst a data phase
- * XXX even on esp100!!!  another case of flooding the bus with I/O reg
- * XXX writes...
- */
-#define esp_maybe_nop(__esp, __eregs) \
-	if((__esp)->erev == esp100) \
-		esp_cmd((__esp), (__eregs), ESP_CMD_NULL)
-
-#define sreg_to_dataphase(__sreg) \
-	((((__sreg) & ESP_STAT_PMASK) == ESP_DOP) ? in_dataout : in_datain)
-
-/* The ESP100 when in synchronous data phase, can mistake a long final
- * REQ pulse from the target as an extra byte, it places whatever is on
- * the data lines into the fifo.  For now, we will assume when this
- * happens that the target is a bit quirky and we don't want to
- * be talking synchronously to it anyways.  Regardless, we need to
- * tell the ESP to eat the extraneous byte so that we can proceed
- * to the next phase.
- */
-static inline int esp100_sync_hwbug(struct NCR_ESP *esp, struct ESP_regs *eregs,
-				    Scsi_Cmnd *sp, int fifocnt)
-{
-	/* Do not touch this piece of code. */
-	if((!(esp->erev == esp100)) ||
-	   (!(sreg_datainp((esp->sreg = esp_read(eregs->esp_status))) && !fifocnt) &&
-	    !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
-		if(sp->SCp.phase == in_dataout)
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		return 0;
-	} else {
-		/* Async mode for this guy. */
-		build_sync_nego_msg(esp, 0, 0);
-
-		/* Ack the bogus byte, but set ATN first. */
-		esp_cmd(esp, eregs, ESP_CMD_SATN);
-		esp_cmd(esp, eregs, ESP_CMD_MOK);
-		return 1;
-	}
-}
-
-/* This closes the window during a selection with a reselect pending, because
- * we use DMA for the selection process the FIFO should hold the correct
- * contents if we get reselected during this process.  So we just need to
- * ack the possible illegal cmd interrupt pending on the esp100.
- */
-static inline int esp100_reconnect_hwbug(struct NCR_ESP *esp,
-					 struct ESP_regs *eregs)
-{
-	volatile unchar junk;
-
-	if(esp->erev != esp100)
-		return 0;
-	junk = esp_read(eregs->esp_intrpt);
-
-	if(junk & ESP_INTR_SR)
-		return 1;
-	return 0;
-}
-
-/* This verifies the BUSID bits during a reselection so that we know which
- * target is talking to us.
- */
-static inline int reconnect_target(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	int it, me = esp->scsi_id_mask, targ = 0;
-
-	if(2 != fcount(esp, eregs))
-		return -1;
-	it = esp_read(eregs->esp_fdata);
-	if(!(it & me))
-		return -1;
-	it &= ~me;
-	if(it & (it - 1))
-		return -1;
-	while(!(it & 1))
-		targ++, it >>= 1;
-	return targ;
-}
-
-/* This verifies the identify from the target so that we know which lun is
- * being reconnected.
- */
-static inline int reconnect_lun(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	int lun;
-
-	if((esp->sreg & ESP_STAT_PMASK) != ESP_MIP)
-		return -1;
-	lun = esp_read(eregs->esp_fdata);
-
-	/* Yes, you read this correctly.  We report lun of zero
-	 * if we see parity error.  ESP reports parity error for
-	 * the lun byte, and this is the only way to hope to recover
-	 * because the target is connected.
-	 */
-	if(esp->sreg & ESP_STAT_PERR)
-		return 0;
-
-	/* Check for illegal bits being set in the lun. */
-	if((lun & 0x40) || !(lun & 0x80))
-		return -1;
-
-	return lun & 7;
-}
-
-/* This puts the driver in a state where it can revitalize a command that
- * is being continued due to reselection.
- */
-static inline void esp_connect(struct NCR_ESP *esp, struct ESP_regs *eregs,
-			       Scsi_Cmnd *sp)
-{
-	struct scsi_device *dp = sp->device;
-	struct esp_device *esp_dev = dp->hostdata;
-
-	if(esp->prev_soff  != esp_dev->sync_max_offset ||
-	   esp->prev_stp   != esp_dev->sync_min_period ||
-	   (esp->erev > esp100a &&
-	    esp->prev_cfg3 != esp->config3[scmd_id(sp)])) {
-		esp->prev_soff = esp_dev->sync_max_offset;
-		esp_write(eregs->esp_soff, esp->prev_soff);
-		esp->prev_stp = esp_dev->sync_min_period;
-		esp_write(eregs->esp_stp, esp->prev_stp);
-		if(esp->erev > esp100a) {
-			esp->prev_cfg3 = esp->config3[scmd_id(sp)];
-			esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-		} 
-	}
-	esp->current_SC = sp;
-}
-
-/* This will place the current working command back into the issue queue
- * if we are to receive a reselection amidst a selection attempt.
- */
-static inline void esp_reconnect(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	if(!esp->disconnected_SC)
-		ESPLOG(("esp%d: Weird, being reselected but disconnected "
-			"command queue is empty.\n", esp->esp_id));
-	esp->snip = 0;
-	esp->current_SC = NULL;
-	sp->SCp.phase = not_issued;
-	append_SC(&esp->issue_SC, sp);
-}
-
-/* Begin message in phase. */
-static int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	esp_maybe_nop(esp, eregs);
-	esp_cmd(esp, eregs, ESP_CMD_TI);
-	esp->msgin_len = 1;
-	esp->msgin_ctr = 0;
-	esp_advance_phase(esp->current_SC, in_msgindone);
-	return do_work_bus;
-}
-
-static inline void advance_sg(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	++sp->SCp.buffer;
-	--sp->SCp.buffers_residual;
-	sp->SCp.this_residual = sp->SCp.buffer->length;
-	if (esp->dma_advance_sg)
-		esp->dma_advance_sg (sp);
-	else
-		sp->SCp.ptr = (char *) virt_to_phys(sg_virt(sp->SCp.buffer));
-
-}
-
-/* Please note that the way I've coded these routines is that I _always_
- * check for a disconnect during any and all information transfer
- * phases.  The SCSI standard states that the target _can_ cause a BUS
- * FREE condition by dropping all MSG/CD/IO/BSY signals.  Also note
- * that during information transfer phases the target controls every
- * change in phase, the only thing the initiator can do is "ask" for
- * a message out phase by driving ATN true.  The target can, and sometimes
- * will, completely ignore this request so we cannot assume anything when
- * we try to force a message out phase to abort/reset a target.  Most of
- * the time the target will eventually be nice and go to message out, so
- * we may have to hold on to our state about what we want to tell the target
- * for some period of time.
- */
-
-/* I think I have things working here correctly.  Even partial transfers
- * within a buffer or sub-buffer should not upset us at all no matter
- * how bad the target and/or ESP fucks things up.
- */
-static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	int thisphase, hmuch;
-
-	ESPDATA(("esp_do_data: "));
-	esp_maybe_nop(esp, eregs);
-	thisphase = sreg_to_dataphase(esp->sreg);
-	esp_advance_phase(SCptr, thisphase);
-	ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT"));
-	hmuch = esp->dma_can_transfer(esp, SCptr);
-
-	/*
-	 * XXX MSch: cater for PIO transfer here; PIO used if hmuch == 0
-	 */
-	if (hmuch) {	/* DMA */
-		/*
-		 * DMA
-		 */
-		ESPDATA(("hmuch<%d> ", hmuch));
-		esp->current_transfer_size = hmuch;
-		esp_setcount(eregs, (esp->fas_premature_intr_workaround ?
-				     (hmuch + 0x40) : hmuch));
-		esp->dma_setup(esp, (__u32)((unsigned long)SCptr->SCp.ptr), 
-			       hmuch, (thisphase == in_datain));
-		ESPDATA(("DMA|TI --> do_intr_end\n"));
-		esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-		return do_intr_end;
-		/*
-		 * end DMA
-		 */
-	} else {
-		/*
-		 * PIO
-		 */
-		int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */
-		int fifocnt = 0;
-		unsigned char *p = phys_to_virt((unsigned long)SCptr->SCp.ptr);
-
-		oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK;
-
-		/*
-		 * polled transfer; ugly, can we make this happen in a DRQ 
-		 * interrupt handler ??
-		 * requires keeping track of state information in host or 
-		 * command struct!
-		 * Problem: I've never seen a DRQ happen on Mac, not even
-		 * with ESP_CMD_DMA ...
-		 */
-
-		/* figure out how much needs to be transferred */
-		hmuch = SCptr->SCp.this_residual;
-		ESPDATA(("hmuch<%d> pio ", hmuch));
-		esp->current_transfer_size = hmuch;
-
-		/* tell the ESP ... */
-		esp_setcount(eregs, hmuch);
-
-		/* loop */
-		while (hmuch) {
-			int j, fifo_stuck = 0, newphase;
-			unsigned long timeout;
-#if 0
-			unsigned long flags;
-#endif
-#if 0
-			if ( i % 10 )
-				ESPDATA(("\r"));
-			else
-				ESPDATA(( /*"\n"*/ "\r"));
-#endif
-#if 0
-			local_irq_save(flags);
-#endif
-			if(thisphase == in_datain) {
-				/* 'go' ... */ 
-				esp_cmd(esp, eregs, ESP_CMD_TI);
-
-				/* wait for data */
-				timeout = 1000000;
-				while (!((esp->sreg=esp_read(eregs->esp_status)) & ESP_STAT_INTR) && --timeout)
-					udelay(2);
-				if (timeout == 0)
-					printk("DRQ datain timeout! \n");
-
-				newphase = esp->sreg & ESP_STAT_PMASK;
-
-				/* see how much we got ... */
-				fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
-
-				if (!fifocnt)
-					fifo_stuck++;
-				else
-					fifo_stuck = 0;
-
-				ESPDATA(("\rgot %d st %x ph %x", fifocnt, esp->sreg, newphase));
-
-				/* read fifo */
-				for(j=0;j<fifocnt;j++)
-					p[i++] = esp_read(eregs->esp_fdata);
-
-				ESPDATA(("(%d) ", i));
-
-				/* how many to go ?? */
-				hmuch -= fifocnt;
-
-				/* break if status phase !! */
-				if(newphase == ESP_STATP) {
-					/* clear int. */
-					esp->ireg = esp_read(eregs->esp_intrpt);
-					break;
-				}
-			} else {
-#define MAX_FIFO 8
-				/* how much will fit ? */
-				int this_count = MAX_FIFO - fifocnt;
-				if (this_count > hmuch)
-					this_count = hmuch;
-
-				/* fill fifo */
-				for(j=0;j<this_count;j++)
-					esp_write(eregs->esp_fdata, p[i++]);
-
-				/* how many left if this goes out ?? */
-				hmuch -= this_count;
-
-				/* 'go' ... */ 
-				esp_cmd(esp, eregs, ESP_CMD_TI);
-
-				/* wait for 'got it' */
-				timeout = 1000000;
-				while (!((esp->sreg=esp_read(eregs->esp_status)) & ESP_STAT_INTR) && --timeout)
-					udelay(2);
-				if (timeout == 0)
-					printk("DRQ dataout timeout!  \n");
-
-				newphase = esp->sreg & ESP_STAT_PMASK;
-
-				/* need to check how much was sent ?? */
-				fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
-
-				ESPDATA(("\rsent %d st %x ph %x", this_count - fifocnt, esp->sreg, newphase));
-
-				ESPDATA(("(%d) ", i));
-
-				/* break if status phase !! */
-				if(newphase == ESP_STATP) {
-					/* clear int. */
-					esp->ireg = esp_read(eregs->esp_intrpt);
-					break;
-				}
-
-			}
-
-			/* clear int. */
-			esp->ireg = esp_read(eregs->esp_intrpt);
-
-			ESPDATA(("ir %x ... ", esp->ireg));
-
-			if (hmuch == 0)
-				ESPDATA(("done! \n"));
-
-#if 0
-			local_irq_restore(flags);
-#endif
-
-			/* check new bus phase */
-			if (newphase != oldphase && i < esp->current_transfer_size) {
-				/* something happened; disconnect ?? */
-				ESPDATA(("phase change, dropped out with %d done ... ", i));
-				break;
-			}
-
-			/* check int. status */
-			if (esp->ireg & ESP_INTR_DC) {
-				/* disconnect */
-				ESPDATA(("disconnect; %d transferred ... ", i));
-				break;
-			} else if (esp->ireg & ESP_INTR_FDONE) {
-				/* function done */
-				ESPDATA(("function done; %d transferred ... ", i));
-				break;
-			}
-
-			/* XXX fixme: bail out on stall */
-			if (fifo_stuck > 10) {
-				/* we're stuck */
-				ESPDATA(("fifo stall; %d transferred ... ", i));
-				break;
-			}
-		}
-
-		ESPDATA(("\n"));
-		/* check successful completion ?? */
-
-		if (thisphase == in_dataout)
-			hmuch += fifocnt; /* stuck?? adjust data pointer ...*/
-
-		/* tell do_data_finale how much was transferred */
-		esp->current_transfer_size -= hmuch;
-
-		/* still not completely sure on this one ... */		
-		return /*do_intr_end*/ do_work_bus /*do_phase_determine*/ ;
-
-		/*
-		 * end PIO
-		 */
-	}
-	return do_intr_end;
-}
-
-/* See how successful the data transfer was. */
-static int esp_do_data_finale(struct NCR_ESP *esp,
-			      struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	struct esp_device *esp_dev = SCptr->device->hostdata;
-	int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
-
-	if(esp->dma_led_off)
-		esp->dma_led_off(esp);
-
-	ESPDATA(("esp_do_data_finale: "));
-
-	if(SCptr->SCp.phase == in_datain) {
-		if(esp->sreg & ESP_STAT_PERR) {
-			/* Yuck, parity error.  The ESP asserts ATN
-			 * so that we can go to message out phase
-			 * immediately and inform the target that
-			 * something bad happened.
-			 */
-			ESPLOG(("esp%d: data bad parity detected.\n",
-				esp->esp_id));
-			esp->cur_msgout[0] = INITIATOR_ERROR;
-			esp->msgout_len = 1;
-		}
-		if(esp->dma_drain)
-			esp->dma_drain(esp);
-	}
-	if(esp->dma_invalidate)
-		esp->dma_invalidate(esp);
-
-	/* This could happen for the above parity error case. */
-	if(!(esp->ireg == ESP_INTR_BSERV)) {
-		/* Please go to msgout phase, please please please... */
-		ESPLOG(("esp%d: !BSERV after data, probably to msgout\n",
-			esp->esp_id));
-		return esp_do_phase_determine(esp, eregs);
-	}	
-
-	/* Check for partial transfers and other horrible events. */
-	fifocnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
-	ecount = esp_getcount(eregs);
-	if(esp->fas_premature_intr_workaround)
-		ecount -= 0x40;
-	bytes_sent = esp->current_transfer_size;
-
-	ESPDATA(("trans_sz=%d, ", bytes_sent));
-	if(!(esp->sreg & ESP_STAT_TCNT))
-		bytes_sent -= ecount;
-	if(SCptr->SCp.phase == in_dataout)
-		bytes_sent -= fifocnt;
-
-	ESPDATA(("bytes_sent=%d (ecount=%d, fifocnt=%d), ", bytes_sent,
-		 ecount, fifocnt));
-
-	/* If we were in synchronous mode, check for peculiarities. */
-	if(esp_dev->sync_max_offset)
-		bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt);
-	else
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-
-	/* Until we are sure of what has happened, we are certainly
-	 * in the dark.
-	 */
-	esp_advance_phase(SCptr, in_the_dark);
-
-	/* Check for premature interrupt condition. Can happen on FAS2x6
-	 * chips. QLogic recommends a workaround by overprogramming the
-	 * transfer counters, but this makes doing scatter-gather impossible.
-	 * Until there is a way to disable scatter-gather for a single target,
-	 * and not only for the entire host adapter as it is now, the workaround
-	 * is way to expensive performance wise.
-	 * Instead, it turns out that when this happens the target has disconnected
-	 * already but it doesn't show in the interrupt register. Compensate for
-	 * that here to try and avoid a SCSI bus reset.
-	 */
-	if(!esp->fas_premature_intr_workaround && (fifocnt == 1) &&
-	   sreg_dataoutp(esp->sreg)) {
-		ESPLOG(("esp%d: Premature interrupt, enabling workaround\n",
-			esp->esp_id));
-#if 0
-		/* Disable scatter-gather operations, they are not possible
-		 * when using this workaround.
-		 */
-		esp->ehost->sg_tablesize = 0;
-		esp->ehost->use_clustering = ENABLE_CLUSTERING;
-		esp->fas_premature_intr_workaround = 1;
-		bytes_sent = 0;
-		if(SCptr->use_sg) {
-			ESPLOG(("esp%d: Aborting scatter-gather operation\n",
-				esp->esp_id));
-			esp->cur_msgout[0] = ABORT;
-			esp->msgout_len = 1;
-			esp->msgout_ctr = 0;
-			esp_cmd(esp, eregs, ESP_CMD_SATN);
-			esp_setcount(eregs, 0xffff);
-			esp_cmd(esp, eregs, ESP_CMD_NULL);
-			esp_cmd(esp, eregs, ESP_CMD_TPAD | ESP_CMD_DMA);
-			return do_intr_end;
-		}
-#else
-		/* Just set the disconnected bit. That's what appears to
-		 * happen anyway. The state machine will pick it up when
-		 * we return.
-		 */
-		esp->ireg |= ESP_INTR_DC;
-#endif
-        }
-
-	if(bytes_sent < 0) {
-		/* I've seen this happen due to lost state in this
-		 * driver.  No idea why it happened, but allowing
-		 * this value to be negative caused things to
-		 * lock up.  This allows greater chance of recovery.
-		 * In fact every time I've seen this, it has been
-		 * a driver bug without question.
-		 */
-		ESPLOG(("esp%d: yieee, bytes_sent < 0!\n", esp->esp_id));
-		ESPLOG(("esp%d: csz=%d fifocount=%d ecount=%d\n",
-			esp->esp_id,
-			esp->current_transfer_size, fifocnt, ecount));
-		ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n",
-			esp->esp_id,
-			SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual));
-		ESPLOG(("esp%d: Forcing async for target %d\n", esp->esp_id, 
-			SCptr->device->id));
-		SCptr->device->borken = 1;
-		esp_dev->sync = 0;
-		bytes_sent = 0;
-	}
-
-	/* Update the state of our transfer. */
-	SCptr->SCp.ptr += bytes_sent;
-	SCptr->SCp.this_residual -= bytes_sent;
-	if(SCptr->SCp.this_residual < 0) {
-		/* shit */
-		ESPLOG(("esp%d: Data transfer overrun.\n", esp->esp_id));
-		SCptr->SCp.this_residual = 0;
-	}
-
-	/* Maybe continue. */
-	if(!bogus_data) {
-		ESPDATA(("!bogus_data, "));
-		/* NO MATTER WHAT, we advance the scatterlist,
-		 * if the target should decide to disconnect
-		 * in between scatter chunks (which is common)
-		 * we could die horribly!  I used to have the sg
-		 * advance occur only if we are going back into
-		 * (or are staying in) a data phase, you can
-		 * imagine the hell I went through trying to
-		 * figure this out.
-		 */
-		if(!SCptr->SCp.this_residual && SCptr->SCp.buffers_residual)
-			advance_sg(esp, SCptr);
-#ifdef DEBUG_ESP_DATA
-		if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) {
-			ESPDATA(("to more data\n"));
-		} else {
-			ESPDATA(("to new phase\n"));
-		}
-#endif
-		return esp_do_phase_determine(esp, eregs);
-	}
-	/* Bogus data, just wait for next interrupt. */
-	ESPLOG(("esp%d: bogus_data during end of data phase\n",
-		esp->esp_id));
-	return do_intr_end;
-}
-
-/* We received a non-good status return at the end of
- * running a SCSI command.  This is used to decide if
- * we should clear our synchronous transfer state for
- * such a device when that happens.
- *
- * The idea is that when spinning up a disk or rewinding
- * a tape, we don't want to go into a loop re-negotiating
- * synchronous capabilities over and over.
- */
-static int esp_should_clear_sync(Scsi_Cmnd *sp)
-{
-	unchar cmd = sp->cmnd[0];
-
-	/* These cases are for spinning up a disk and
-	 * waiting for that spinup to complete.
-	 */
-	if(cmd == START_STOP)
-		return 0;
-
-	if(cmd == TEST_UNIT_READY)
-		return 0;
-
-	/* One more special case for SCSI tape drives,
-	 * this is what is used to probe the device for
-	 * completion of a rewind or tape load operation.
-	 */
-	if(sp->device->type == TYPE_TAPE && cmd == MODE_SENSE)
-		return 0;
-
-	return 1;
-}
-
-/* Either a command is completing or a target is dropping off the bus
- * to continue the command in the background so we can do other work.
- */
-static int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	int rval;
-
-	rval = skipahead2(esp, eregs, SCptr, in_status, in_msgindone, in_freeing);
-	if(rval)
-		return rval;
-
-	if(esp->ireg != ESP_INTR_DC) {
-		ESPLOG(("esp%d: Target will not disconnect\n", esp->esp_id));
-		return do_reset_bus; /* target will not drop BSY... */
-	}
-	esp->msgout_len = 0;
-	esp->prevmsgout = NOP;
-	if(esp->prevmsgin == COMMAND_COMPLETE) {
-		struct esp_device *esp_dev = SCptr->device->hostdata;
-		/* Normal end of nexus. */
-		if(esp->disconnected_SC)
-			esp_cmd(esp, eregs, ESP_CMD_ESEL);
-
-		if(SCptr->SCp.Status != GOOD &&
-		   SCptr->SCp.Status != CONDITION_GOOD &&
-		   ((1<<scmd_id(SCptr)) & esp->targets_present) &&
-		   esp_dev->sync && esp_dev->sync_max_offset) {
-			/* SCSI standard says that the synchronous capabilities
-			 * should be renegotiated at this point.  Most likely
-			 * we are about to request sense from this target
-			 * in which case we want to avoid using sync
-			 * transfers until we are sure of the current target
-			 * state.
-			 */
-			ESPMISC(("esp: Status <%d> for target %d lun %d\n",
-				 SCptr->SCp.Status, SCptr->device->id, SCptr->device->lun));
-
-			/* But don't do this when spinning up a disk at
-			 * boot time while we poll for completion as it
-			 * fills up the console with messages.  Also, tapes
-			 * can report not ready many times right after
-			 * loading up a tape.
-			 */
-			if(esp_should_clear_sync(SCptr) != 0)
-				esp_dev->sync = 0;
-		}
-		ESPDISC(("F<%02x,%02x>", SCptr->device->id, SCptr->device->lun));
-		esp_done(esp, ((SCptr->SCp.Status & 0xff) |
-			       ((SCptr->SCp.Message & 0xff)<<8) |
-			       (DID_OK << 16)));
-	} else if(esp->prevmsgin == DISCONNECT) {
-		/* Normal disconnect. */
-		esp_cmd(esp, eregs, ESP_CMD_ESEL);
-		ESPDISC(("D<%02x,%02x>", SCptr->device->id, SCptr->device->lun));
-		append_SC(&esp->disconnected_SC, SCptr);
-		esp->current_SC = NULL;
-		if(esp->issue_SC)
-			esp_exec_cmd(esp);
-	} else {
-		/* Driver bug, we do not expect a disconnect here
-		 * and should not have advanced the state engine
-		 * to in_freeing.
-		 */
-		ESPLOG(("esp%d: last msg not disc and not cmd cmplt.\n",
-			esp->esp_id));
-		return do_reset_bus;
-	}
-	return do_intr_end;
-}
-
-/* When a reselect occurs, and we cannot find the command to
- * reconnect to in our queues, we do this.
- */
-static int esp_bad_reconnect(struct NCR_ESP *esp)
-{
-	Scsi_Cmnd *sp;
-
-	ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
-		esp->esp_id));
-	ESPLOG(("QUEUE DUMP\n"));
-	sp = esp->issue_SC;
-	ESPLOG(("esp%d: issue_SC[", esp->esp_id));
-	while(sp) {
-		ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
-		sp = (Scsi_Cmnd *) sp->host_scribble;
-	}
-	ESPLOG(("]\n"));
-	sp = esp->current_SC;
-	ESPLOG(("esp%d: current_SC[", esp->esp_id));
-	while(sp) {
-		ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
-		sp = (Scsi_Cmnd *) sp->host_scribble;
-	}
-	ESPLOG(("]\n"));
-	sp = esp->disconnected_SC;
-	ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
-	while(sp) {
-		ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
-		sp = (Scsi_Cmnd *) sp->host_scribble;
-	}
-	ESPLOG(("]\n"));
-	return do_reset_bus;
-}
-
-/* Do the needy when a target tries to reconnect to us. */
-static int esp_do_reconnect(struct NCR_ESP *esp, 
-			    struct ESP_regs *eregs)
-{
-	int lun, target;
-	Scsi_Cmnd *SCptr;
-
-	/* Check for all bogus conditions first. */
-	target = reconnect_target(esp, eregs);
-	if(target < 0) {
-		ESPDISC(("bad bus bits\n"));
-		return do_reset_bus;
-	}
-	lun = reconnect_lun(esp, eregs);
-	if(lun < 0) {
-		ESPDISC(("target=%2x, bad identify msg\n", target));
-		return do_reset_bus;
-	}
-
-	/* Things look ok... */
-	ESPDISC(("R<%02x,%02x>", target, lun));
-
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	if(esp100_reconnect_hwbug(esp, eregs))
-		return do_reset_bus;
-	esp_cmd(esp, eregs, ESP_CMD_NULL);
-
-	SCptr = remove_SC(&esp->disconnected_SC, (unchar) target, (unchar) lun);
-	if(!SCptr)
-		return esp_bad_reconnect(esp);
-
-	esp_connect(esp, eregs, SCptr);
-	esp_cmd(esp, eregs, ESP_CMD_MOK);
-
-	/* Reconnect implies a restore pointers operation. */
-	esp_restore_pointers(esp, SCptr);
-
-	esp->snip = 0;
-	esp_advance_phase(SCptr, in_the_dark);
-	return do_intr_end;
-}
-
-/* End of NEXUS (hopefully), pick up status + message byte then leave if
- * all goes well.
- */
-static int esp_do_status(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	int intr, rval;
-
-	rval = skipahead1(esp, eregs, SCptr, in_the_dark, in_status);
-	if(rval)
-		return rval;
-
-	intr = esp->ireg;
-	ESPSTAT(("esp_do_status: "));
-	if(intr != ESP_INTR_DC) {
-		int message_out = 0; /* for parity problems */
-
-		/* Ack the message. */
-		ESPSTAT(("ack msg, "));
-		esp_cmd(esp, eregs, ESP_CMD_MOK);
-
-		if(esp->dma_poll)
-			esp->dma_poll(esp, (unsigned char *) esp->esp_command);
-
-		ESPSTAT(("got something, "));
-		/* ESP chimes in with one of
-		 *
-		 * 1) function done interrupt:
-		 *	both status and message in bytes
-		 *	are available
-		 *
-		 * 2) bus service interrupt:
-		 *	only status byte was acquired
-		 *
-		 * 3) Anything else:
-		 *	can't happen, but we test for it
-		 *	anyways
-		 *
-		 * ALSO: If bad parity was detected on either
-		 *       the status _or_ the message byte then
-		 *       the ESP has asserted ATN on the bus
-		 *       and we must therefore wait for the
-		 *       next phase change.
-		 */
-		if(intr & ESP_INTR_FDONE) {
-			/* We got it all, hallejulia. */
-			ESPSTAT(("got both, "));
-			SCptr->SCp.Status = esp->esp_command[0];
-			SCptr->SCp.Message = esp->esp_command[1];
-			esp->prevmsgin = SCptr->SCp.Message;
-			esp->cur_msgin[0] = SCptr->SCp.Message;
-			if(esp->sreg & ESP_STAT_PERR) {
-				/* There was bad parity for the
-				 * message byte, the status byte
-				 * was ok.
-				 */
-				message_out = MSG_PARITY_ERROR;
-			}
-		} else if(intr == ESP_INTR_BSERV) {
-			/* Only got status byte. */
-			ESPLOG(("esp%d: got status only, ", esp->esp_id));
-			if(!(esp->sreg & ESP_STAT_PERR)) {
-				SCptr->SCp.Status = esp->esp_command[0];
-				SCptr->SCp.Message = 0xff;
-			} else {
-				/* The status byte had bad parity.
-				 * we leave the scsi_pointer Status
-				 * field alone as we set it to a default
-				 * of CHECK_CONDITION in esp_queue.
-				 */
-				message_out = INITIATOR_ERROR;
-			}
-		} else {
-			/* This shouldn't happen ever. */
-			ESPSTAT(("got bolixed\n"));
-			esp_advance_phase(SCptr, in_the_dark);
-			return esp_do_phase_determine(esp, eregs);
-		}
-
-		if(!message_out) {
-			ESPSTAT(("status=%2x msg=%2x, ", SCptr->SCp.Status,
-				SCptr->SCp.Message));
-			if(SCptr->SCp.Message == COMMAND_COMPLETE) {
-				ESPSTAT(("and was COMMAND_COMPLETE\n"));
-				esp_advance_phase(SCptr, in_freeing);
-				return esp_do_freebus(esp, eregs);
-			} else {
-				ESPLOG(("esp%d: and _not_ COMMAND_COMPLETE\n",
-					esp->esp_id));
-				esp->msgin_len = esp->msgin_ctr = 1;
-				esp_advance_phase(SCptr, in_msgindone);
-				return esp_do_msgindone(esp, eregs);
-			}
-		} else {
-			/* With luck we'll be able to let the target
-			 * know that bad parity happened, it will know
-			 * which byte caused the problems and send it
-			 * again.  For the case where the status byte
-			 * receives bad parity, I do not believe most
-			 * targets recover very well.  We'll see.
-			 */
-			ESPLOG(("esp%d: bad parity somewhere mout=%2x\n",
-				esp->esp_id, message_out));
-			esp->cur_msgout[0] = message_out;
-			esp->msgout_len = esp->msgout_ctr = 1;
-			esp_advance_phase(SCptr, in_the_dark);
-			return esp_do_phase_determine(esp, eregs);
-		}
-	} else {
-		/* If we disconnect now, all hell breaks loose. */
-		ESPLOG(("esp%d: whoops, disconnect\n", esp->esp_id));
-		esp_advance_phase(SCptr, in_the_dark);
-		return esp_do_phase_determine(esp, eregs);
-	}
-}
-
-static int esp_enter_status(struct NCR_ESP *esp,
-			    struct ESP_regs *eregs)
-{
-	unchar thecmd = ESP_CMD_ICCSEQ;
-
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-
-	if(esp->do_pio_cmds) {
-		esp_advance_phase(esp->current_SC, in_status);
-		esp_cmd(esp, eregs, thecmd);
-		while(!(esp_read(esp->eregs->esp_status) & ESP_STAT_INTR));
-		esp->esp_command[0] = esp_read(eregs->esp_fdata);
-                while(!(esp_read(esp->eregs->esp_status) & ESP_STAT_INTR));
-                esp->esp_command[1] = esp_read(eregs->esp_fdata);
-	} else {
-		esp->esp_command[0] = esp->esp_command[1] = 0xff;
-		esp_write(eregs->esp_tclow, 2);
-		esp_write(eregs->esp_tcmed, 0);
-		esp->dma_init_read(esp, esp->esp_command_dvma, 2);
-		thecmd |= ESP_CMD_DMA;
-		esp_cmd(esp, eregs, thecmd);
-		esp_advance_phase(esp->current_SC, in_status);
-	}
-
-	return esp_do_status(esp, eregs);
-}
-
-static int esp_disconnect_amidst_phases(struct NCR_ESP *esp,
-					struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *sp = esp->current_SC;
-	struct esp_device *esp_dev = sp->device->hostdata;
-
-	/* This means real problems if we see this
-	 * here.  Unless we were actually trying
-	 * to force the device to abort/reset.
-	 */
-	ESPLOG(("esp%d: Disconnect amidst phases, ", esp->esp_id));
-	ESPLOG(("pphase<%s> cphase<%s>, ",
-		phase_string(sp->SCp.phase),
-		phase_string(sp->SCp.sent_command)));
-
-	if(esp->disconnected_SC)
-		esp_cmd(esp, eregs, ESP_CMD_ESEL);
-
-	switch(esp->cur_msgout[0]) {
-	default:
-		/* We didn't expect this to happen at all. */
-		ESPLOG(("device is bolixed\n"));
-		esp_advance_phase(sp, in_tgterror);
-		esp_done(esp, (DID_ERROR << 16));
-		break;
-
-	case BUS_DEVICE_RESET:
-		ESPLOG(("device reset successful\n"));
-		esp_dev->sync_max_offset = 0;
-		esp_dev->sync_min_period = 0;
-		esp_dev->sync = 0;
-		esp_advance_phase(sp, in_resetdev);
-		esp_done(esp, (DID_RESET << 16));
-		break;
-
-	case ABORT:
-		ESPLOG(("device abort successful\n"));
-		esp_advance_phase(sp, in_abortone);
-		esp_done(esp, (DID_ABORT << 16));
-		break;
-
-	};
-	return do_intr_end;
-}
-
-static int esp_enter_msgout(struct NCR_ESP *esp,
-			    struct ESP_regs *eregs)
-{
-	esp_advance_phase(esp->current_SC, in_msgout);
-	return esp_do_msgout(esp, eregs);
-}
-
-static int esp_enter_msgin(struct NCR_ESP *esp,
-			   struct ESP_regs *eregs)
-{
-	esp_advance_phase(esp->current_SC, in_msgin);
-	return esp_do_msgin(esp, eregs);
-}
-
-static int esp_enter_cmd(struct NCR_ESP *esp,
-			 struct ESP_regs *eregs)
-{
-	esp_advance_phase(esp->current_SC, in_cmdbegin);
-	return esp_do_cmdbegin(esp, eregs);
-}
-
-static int esp_enter_badphase(struct NCR_ESP *esp,
-			      struct ESP_regs *eregs)
-{
-	ESPLOG(("esp%d: Bizarre bus phase %2x.\n", esp->esp_id,
-		esp->sreg & ESP_STAT_PMASK));
-	return do_reset_bus;
-}
-
-typedef int (*espfunc_t)(struct NCR_ESP *,
-			 struct ESP_regs *);
-
-static espfunc_t phase_vector[] = {
-	esp_do_data,		/* ESP_DOP */
-	esp_do_data,		/* ESP_DIP */
-	esp_enter_cmd,		/* ESP_CMDP */
-	esp_enter_status,	/* ESP_STATP */
-	esp_enter_badphase,	/* ESP_STAT_PMSG */
-	esp_enter_badphase,	/* ESP_STAT_PMSG | ESP_STAT_PIO */
-	esp_enter_msgout,	/* ESP_MOP */
-	esp_enter_msgin,	/* ESP_MIP */
-};
-
-/* The target has control of the bus and we have to see where it has
- * taken us.
- */
-static int esp_do_phase_determine(struct NCR_ESP *esp,
-				  struct ESP_regs *eregs)
-{
-	if ((esp->ireg & ESP_INTR_DC) != 0)
-		return esp_disconnect_amidst_phases(esp, eregs);
-	return phase_vector[esp->sreg & ESP_STAT_PMASK](esp, eregs);
-}
-
-/* First interrupt after exec'ing a cmd comes here. */
-static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	struct esp_device *esp_dev = SCptr->device->hostdata;
-	int cmd_bytes_sent, fcnt;
-
-	fcnt = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES);
-	cmd_bytes_sent = esp->dma_bytes_sent(esp, fcnt);
-	if(esp->dma_invalidate)
-		esp->dma_invalidate(esp);
-
-	/* Let's check to see if a reselect happened
-	 * while we we're trying to select.  This must
-	 * be checked first.
-	 */
-	if(esp->ireg == (ESP_INTR_RSEL | ESP_INTR_FDONE)) {
-		esp_reconnect(esp, SCptr);
-		return esp_do_reconnect(esp, eregs);
-	}
-
-	/* Looks like things worked, we should see a bus service &
-	 * a function complete interrupt at this point.  Note we
-	 * are doing a direct comparison because we don't want to
-	 * be fooled into thinking selection was successful if
-	 * ESP_INTR_DC is set, see below.
-	 */
-	if(esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) {
-		/* target speaks... */
-		esp->targets_present |= (1<<scmd_id(SCptr));
-
-		/* What if the target ignores the sdtr? */
-		if(esp->snip)
-			esp_dev->sync = 1;
-
-		/* See how far, if at all, we got in getting
-		 * the information out to the target.
-		 */
-		switch(esp->seqreg) {
-		default:
-
-		case ESP_STEP_ASEL:
-			/* Arbitration won, target selected, but
-			 * we are in some phase which is not command
-			 * phase nor is it message out phase.
-			 *
-			 * XXX We've confused the target, obviously.
-			 * XXX So clear it's state, but we also end
-			 * XXX up clearing everyone elses.  That isn't
-			 * XXX so nice.  I'd like to just reset this
-			 * XXX target, but if I cannot even get it's
-			 * XXX attention and finish selection to talk
-			 * XXX to it, there is not much more I can do.
-			 * XXX If we have a loaded bus we're going to
-			 * XXX spend the next second or so renegotiating
-			 * XXX for synchronous transfers.
-			 */
-			ESPLOG(("esp%d: STEP_ASEL for tgt %d\n",
-				esp->esp_id, SCptr->device->id));
-
-		case ESP_STEP_SID:
-			/* Arbitration won, target selected, went
-			 * to message out phase, sent one message
-			 * byte, then we stopped.  ATN is asserted
-			 * on the SCSI bus and the target is still
-			 * there hanging on.  This is a legal
-			 * sequence step if we gave the ESP a select
-			 * and stop command.
-			 *
-			 * XXX See above, I could set the borken flag
-			 * XXX in the device struct and retry the
-			 * XXX command.  But would that help for
-			 * XXX tagged capable targets?
-			 */
-
-		case ESP_STEP_NCMD:
-			/* Arbitration won, target selected, maybe
-			 * sent the one message byte in message out
-			 * phase, but we did not go to command phase
-			 * in the end.  Actually, we could have sent
-			 * only some of the message bytes if we tried
-			 * to send out the entire identify and tag
-			 * message using ESP_CMD_SA3.
-			 */
-			cmd_bytes_sent = 0;
-			break;
-
-		case ESP_STEP_PPC:
-			/* No, not the powerPC pinhead.  Arbitration
-			 * won, all message bytes sent if we went to
-			 * message out phase, went to command phase
-			 * but only part of the command was sent.
-			 *
-			 * XXX I've seen this, but usually in conjunction
-			 * XXX with a gross error which appears to have
-			 * XXX occurred between the time I told the
-			 * XXX ESP to arbitrate and when I got the
-			 * XXX interrupt.  Could I have misloaded the
-			 * XXX command bytes into the fifo?  Actually,
-			 * XXX I most likely missed a phase, and therefore
-			 * XXX went into never never land and didn't even
-			 * XXX know it.  That was the old driver though.
-			 * XXX What is even more peculiar is that the ESP
-			 * XXX showed the proper function complete and
-			 * XXX bus service bits in the interrupt register.
-			 */
-
-		case ESP_STEP_FINI4:
-		case ESP_STEP_FINI5:
-		case ESP_STEP_FINI6:
-		case ESP_STEP_FINI7:
-			/* Account for the identify message */
-			if(SCptr->SCp.phase == in_slct_norm)
-				cmd_bytes_sent -= 1;
-		};
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
-
-		/* Be careful, we could really get fucked during synchronous
-		 * data transfers if we try to flush the fifo now.
-		 */
-		if(!fcnt && /* Fifo is empty and... */
-		   /* either we are not doing synchronous transfers or... */
-		   (!esp_dev->sync_max_offset ||
-		    /* We are not going into data in phase. */
-		    ((esp->sreg & ESP_STAT_PMASK) != ESP_DIP)))
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* flush is safe */
-
-		/* See how far we got if this is not a slow command. */
-		if(!esp->esp_slowcmd) {
-			if(cmd_bytes_sent < 0)
-				cmd_bytes_sent = 0;
-			if(cmd_bytes_sent != SCptr->cmd_len) {
-				/* Crapola, mark it as a slowcmd
-				 * so that we have some chance of
-				 * keeping the command alive with
-				 * good luck.
-				 *
-				 * XXX Actually, if we didn't send it all
-				 * XXX this means either we didn't set things
-				 * XXX up properly (driver bug) or the target
-				 * XXX or the ESP detected parity on one of
-				 * XXX the command bytes.  This makes much
-				 * XXX more sense, and therefore this code
-				 * XXX should be changed to send out a
-				 * XXX parity error message or if the status
-				 * XXX register shows no parity error then
-				 * XXX just expect the target to bring the
-				 * XXX bus into message in phase so that it
-				 * XXX can send us the parity error message.
-				 * XXX SCSI sucks...
-				 */
-				esp->esp_slowcmd = 1;
-				esp->esp_scmdp = &(SCptr->cmnd[cmd_bytes_sent]);
-				esp->esp_scmdleft = (SCptr->cmd_len - cmd_bytes_sent);
-			}
-		}
-
-		/* Now figure out where we went. */
-		esp_advance_phase(SCptr, in_the_dark);
-		return esp_do_phase_determine(esp, eregs);
-	}
-
-	/* Did the target even make it? */
-	if(esp->ireg == ESP_INTR_DC) {
-		/* wheee... nobody there or they didn't like
-		 * what we told it to do, clean up.
-		 */
-
-		/* If anyone is off the bus, but working on
-		 * a command in the background for us, tell
-		 * the ESP to listen for them.
-		 */
-		if(esp->disconnected_SC)
-			esp_cmd(esp, eregs, ESP_CMD_ESEL);
-
-		if(((1<<SCptr->device->id) & esp->targets_present) &&
-		   esp->seqreg && esp->cur_msgout[0] == EXTENDED_MESSAGE &&
-		   (SCptr->SCp.phase == in_slct_msg ||
-		    SCptr->SCp.phase == in_slct_stop)) {
-			/* shit */
-			esp->snip = 0;
-			ESPLOG(("esp%d: Failed synchronous negotiation for target %d "
-				"lun %d\n", esp->esp_id, SCptr->device->id, SCptr->device->lun));
-			esp_dev->sync_max_offset = 0;
-			esp_dev->sync_min_period = 0;
-			esp_dev->sync = 1; /* so we don't negotiate again */
-
-			/* Run the command again, this time though we
-			 * won't try to negotiate for synchronous transfers.
-			 *
-			 * XXX I'd like to do something like send an
-			 * XXX INITIATOR_ERROR or ABORT message to the
-			 * XXX target to tell it, "Sorry I confused you,
-			 * XXX please come back and I will be nicer next
-			 * XXX time".  But that requires having the target
-			 * XXX on the bus, and it has dropped BSY on us.
-			 */
-			esp->current_SC = NULL;
-			esp_advance_phase(SCptr, not_issued);
-			prepend_SC(&esp->issue_SC, SCptr);
-			esp_exec_cmd(esp);
-			return do_intr_end;
-		}
-
-		/* Ok, this is normal, this is what we see during boot
-		 * or whenever when we are scanning the bus for targets.
-		 * But first make sure that is really what is happening.
-		 */
-		if(((1<<SCptr->device->id) & esp->targets_present)) {
-			ESPLOG(("esp%d: Warning, live target %d not responding to "
-				"selection.\n", esp->esp_id, SCptr->device->id));
-
-			/* This _CAN_ happen.  The SCSI standard states that
-			 * the target is to _not_ respond to selection if
-			 * _it_ detects bad parity on the bus for any reason.
-			 * Therefore, we assume that if we've talked successfully
-			 * to this target before, bad parity is the problem.
-			 */
-			esp_done(esp, (DID_PARITY << 16));
-		} else {
-			/* Else, there really isn't anyone there. */
-			ESPMISC(("esp: selection failure, maybe nobody there?\n"));
-			ESPMISC(("esp: target %d lun %d\n",
-				 SCptr->device->id, SCptr->device->lun));
-			esp_done(esp, (DID_BAD_TARGET << 16));
-		}
-		return do_intr_end;
-	}
-
-
-	ESPLOG(("esp%d: Selection failure.\n", esp->esp_id));
-	printk("esp%d: Currently -- ", esp->esp_id);
-	esp_print_ireg(esp->ireg);
-	printk(" ");
-	esp_print_statreg(esp->sreg);
-	printk(" ");
-	esp_print_seqreg(esp->seqreg);
-	printk("\n");
-	printk("esp%d: New -- ", esp->esp_id);
-	esp->sreg = esp_read(eregs->esp_status);
-	esp->seqreg = esp_read(eregs->esp_sstep);
-	esp->ireg = esp_read(eregs->esp_intrpt);
-	esp_print_ireg(esp->ireg);
-	printk(" ");
-	esp_print_statreg(esp->sreg);
-	printk(" ");
-	esp_print_seqreg(esp->seqreg);
-	printk("\n");
-	ESPLOG(("esp%d: resetting bus\n", esp->esp_id));
-	return do_reset_bus; /* ugh... */
-}
-
-/* Continue reading bytes for msgin phase. */
-static int esp_do_msgincont(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	if(esp->ireg & ESP_INTR_BSERV) {
-		/* in the right phase too? */
-		if((esp->sreg & ESP_STAT_PMASK) == ESP_MIP) {
-			/* phew... */
-			esp_cmd(esp, eregs, ESP_CMD_TI);
-			esp_advance_phase(esp->current_SC, in_msgindone);
-			return do_intr_end;
-		}
-
-		/* We changed phase but ESP shows bus service,
-		 * in this case it is most likely that we, the
-		 * hacker who has been up for 20hrs straight
-		 * staring at the screen, drowned in coffee
-		 * smelling like retched cigarette ashes
-		 * have miscoded something..... so, try to
-		 * recover as best we can.
-		 */
-		ESPLOG(("esp%d: message in mis-carriage.\n", esp->esp_id));
-	}
-	esp_advance_phase(esp->current_SC, in_the_dark);
-	return do_phase_determine;
-}
-
-static int check_singlebyte_msg(struct NCR_ESP *esp,
-				struct ESP_regs *eregs)
-{
-	esp->prevmsgin = esp->cur_msgin[0];
-	if(esp->cur_msgin[0] & 0x80) {
-		/* wheee... */
-		ESPLOG(("esp%d: target sends identify amidst phases\n",
-			esp->esp_id));
-		esp_advance_phase(esp->current_SC, in_the_dark);
-		return 0;
-	} else if(((esp->cur_msgin[0] & 0xf0) == 0x20) ||
-		  (esp->cur_msgin[0] == EXTENDED_MESSAGE)) {
-		esp->msgin_len = 2;
-		esp_advance_phase(esp->current_SC, in_msgincont);
-		return 0;
-	}
-	esp_advance_phase(esp->current_SC, in_the_dark);
-	switch(esp->cur_msgin[0]) {
-	default:
-		/* We don't want to hear about it. */
-		ESPLOG(("esp%d: msg %02x which we don't know about\n", esp->esp_id,
-			esp->cur_msgin[0]));
-		return MESSAGE_REJECT;
-
-	case NOP:
-		ESPLOG(("esp%d: target %d sends a nop\n", esp->esp_id,
-			esp->current_SC->device->id));
-		return 0;
-
-	case RESTORE_POINTERS:
-		/* In this case we might also have to backup the
-		 * "slow command" pointer.  It is rare to get such
-		 * a save/restore pointer sequence so early in the
-		 * bus transition sequences, but cover it.
-		 */
-		if(esp->esp_slowcmd) {
-			esp->esp_scmdleft = esp->current_SC->cmd_len;
-			esp->esp_scmdp = &esp->current_SC->cmnd[0];
-		}
-		esp_restore_pointers(esp, esp->current_SC);
-		return 0;
-
-	case SAVE_POINTERS:
-		esp_save_pointers(esp, esp->current_SC);
-		return 0;
-
-	case COMMAND_COMPLETE:
-	case DISCONNECT:
-		/* Freeing the bus, let it go. */
-		esp->current_SC->SCp.phase = in_freeing;
-		return 0;
-
-	case MESSAGE_REJECT:
-		ESPMISC(("msg reject, "));
-		if(esp->prevmsgout == EXTENDED_MESSAGE) {
-			struct esp_device *esp_dev = esp->current_SC->device->hostdata;
-
-			/* Doesn't look like this target can
-			 * do synchronous or WIDE transfers.
-			 */
-			ESPSDTR(("got reject, was trying nego, clearing sync/WIDE\n"));
-			esp_dev->sync = 1;
-			esp_dev->wide = 1;
-			esp_dev->sync_min_period = 0;
-			esp_dev->sync_max_offset = 0;
-			return 0;
-		} else {
-			ESPMISC(("not sync nego, sending ABORT\n"));
-			return ABORT;
-		}
-	};
-}
-
-/* Target negotiates for synchronous transfers before we do, this
- * is legal although very strange.  What is even funnier is that
- * the SCSI2 standard specifically recommends against targets doing
- * this because so many initiators cannot cope with this occurring.
- */
-static int target_with_ants_in_pants(struct NCR_ESP *esp,
-				     Scsi_Cmnd *SCptr,
-				     struct esp_device *esp_dev)
-{
-	if(esp_dev->sync || SCptr->device->borken) {
-		/* sorry, no can do */
-		ESPSDTR(("forcing to async, "));
-		build_sync_nego_msg(esp, 0, 0);
-		esp_dev->sync = 1;
-		esp->snip = 1;
-		ESPLOG(("esp%d: hoping for msgout\n", esp->esp_id));
-		esp_advance_phase(SCptr, in_the_dark);
-		return EXTENDED_MESSAGE;
-	}
-
-	/* Ok, we'll check them out... */
-	return 0;
-}
-
-static void sync_report(struct NCR_ESP *esp)
-{
-	int msg3, msg4;
-	char *type;
-
-	msg3 = esp->cur_msgin[3];
-	msg4 = esp->cur_msgin[4];
-	if(msg4) {
-		int hz = 1000000000 / (msg3 * 4);
-		int integer = hz / 1000000;
-		int fraction = (hz - (integer * 1000000)) / 10000;
-		if((msg3 * 4) < 200) {
-			type = "FAST";
-		} else {
-			type = "synchronous";
-		}
-
-		/* Do not transform this back into one big printk
-		 * again, it triggers a bug in our sparc64-gcc272
-		 * sibling call optimization.  -DaveM
-		 */
-		ESPLOG((KERN_INFO "esp%d: target %d ",
-			esp->esp_id, esp->current_SC->device->id));
-		ESPLOG(("[period %dns offset %d %d.%02dMHz ",
-			(int) msg3 * 4, (int) msg4,
-			integer, fraction));
-		ESPLOG(("%s SCSI%s]\n", type,
-			(((msg3 * 4) < 200) ? "-II" : "")));
-	} else {
-		ESPLOG((KERN_INFO "esp%d: target %d asynchronous\n",
-			esp->esp_id, esp->current_SC->device->id));
-	}
-}
-
-static int check_multibyte_msg(struct NCR_ESP *esp,
-			       struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	struct esp_device *esp_dev = SCptr->device->hostdata;
-	unchar regval = 0;
-	int message_out = 0;
-
-	ESPSDTR(("chk multibyte msg: "));
-	if(esp->cur_msgin[2] == EXTENDED_SDTR) {
-		int period = esp->cur_msgin[3];
-		int offset = esp->cur_msgin[4];
-
-		ESPSDTR(("is sync nego response, "));
-		if(!esp->snip) {
-			int rval;
-
-			/* Target negotiates first! */
-			ESPSDTR(("target jumps the gun, "));
-			message_out = EXTENDED_MESSAGE; /* we must respond */
-			rval = target_with_ants_in_pants(esp, SCptr, esp_dev);
-			if(rval)
-				return rval;
-		}
-
-		ESPSDTR(("examining sdtr, "));
-
-		/* Offset cannot be larger than ESP fifo size. */
-		if(offset > 15) {
-			ESPSDTR(("offset too big %2x, ", offset));
-			offset = 15;
-			ESPSDTR(("sending back new offset\n"));
-			build_sync_nego_msg(esp, period, offset);
-			return EXTENDED_MESSAGE;
-		}
-
-		if(offset && period > esp->max_period) {
-			/* Yeee, async for this slow device. */
-			ESPSDTR(("period too long %2x, ", period));
-			build_sync_nego_msg(esp, 0, 0);
-			ESPSDTR(("hoping for msgout\n"));
-			esp_advance_phase(esp->current_SC, in_the_dark);
-			return EXTENDED_MESSAGE;
-		} else if (offset && period < esp->min_period) {
-			ESPSDTR(("period too short %2x, ", period));
-			period = esp->min_period;
-			if(esp->erev > esp236)
-				regval = 4;
-			else
-				regval = 5;
-		} else if(offset) {
-			int tmp;
-
-			ESPSDTR(("period is ok, "));
-			tmp = esp->ccycle / 1000;
-			regval = (((period << 2) + tmp - 1) / tmp);
-			if(regval && (esp->erev > esp236)) {
-				if(period >= 50)
-					regval--;
-			}
-		}
-
-		if(offset) {
-			unchar bit;
-
-			esp_dev->sync_min_period = (regval & 0x1f);
-			esp_dev->sync_max_offset = (offset | esp->radelay);
-			if(esp->erev > esp236) {
-				if(esp->erev == fas100a)
-					bit = ESP_CONFIG3_FAST;
-				else
-					bit = ESP_CONFIG3_FSCSI;
-				if(period < 50)
-					esp->config3[SCptr->device->id] |= bit;
-				else
-					esp->config3[SCptr->device->id] &= ~bit;
-				esp->prev_cfg3 = esp->config3[SCptr->device->id];
-				esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-			}
-			esp->prev_soff = esp_dev->sync_min_period;
-			esp_write(eregs->esp_soff, esp->prev_soff);
-			esp->prev_stp = esp_dev->sync_max_offset;
-			esp_write(eregs->esp_stp, esp->prev_stp);
-
-			ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
-				esp_dev->sync_max_offset,
-				esp_dev->sync_min_period,
-				esp->config3[scmd_id(SCptr)]));
-
-			esp->snip = 0;
-		} else if(esp_dev->sync_max_offset) {
-			unchar bit;
-
-			/* back to async mode */
-			ESPSDTR(("unaccaptable sync nego, forcing async\n"));
-			esp_dev->sync_max_offset = 0;
-			esp_dev->sync_min_period = 0;
-			esp->prev_soff = 0;
-			esp_write(eregs->esp_soff, 0);
-			esp->prev_stp = 0;
-			esp_write(eregs->esp_stp, 0);
-			if(esp->erev > esp236) {
-				if(esp->erev == fas100a)
-					bit = ESP_CONFIG3_FAST;
-				else
-					bit = ESP_CONFIG3_FSCSI;
-				esp->config3[SCptr->device->id] &= ~bit;
-				esp->prev_cfg3 = esp->config3[SCptr->device->id];
-				esp_write(eregs->esp_cfg3, esp->prev_cfg3);
-			}
-		}
-
-		sync_report(esp);
-
-		ESPSDTR(("chk multibyte msg: sync is known, "));
-		esp_dev->sync = 1;
-
-		if(message_out) {
-			ESPLOG(("esp%d: sending sdtr back, hoping for msgout\n",
-				esp->esp_id));
-			build_sync_nego_msg(esp, period, offset);
-			esp_advance_phase(SCptr, in_the_dark);
-			return EXTENDED_MESSAGE;
-		}
-
-		ESPSDTR(("returning zero\n"));
-		esp_advance_phase(SCptr, in_the_dark); /* ...or else! */
-		return 0;
-	} else if(esp->cur_msgin[2] == EXTENDED_WDTR) {
-		ESPLOG(("esp%d: AIEEE wide msg received\n", esp->esp_id));
-		message_out = MESSAGE_REJECT;
-	} else if(esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) {
-		ESPLOG(("esp%d: rejecting modify data ptr msg\n", esp->esp_id));
-		message_out = MESSAGE_REJECT;
-	}
-	esp_advance_phase(SCptr, in_the_dark);
-	return message_out;
-}
-
-static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	int message_out = 0, it = 0, rval;
-
-	rval = skipahead1(esp, eregs, SCptr, in_msgin, in_msgindone);
-	if(rval)
-		return rval;
-	if(SCptr->SCp.sent_command != in_status) {
-		if(!(esp->ireg & ESP_INTR_DC)) {
-			if(esp->msgin_len && (esp->sreg & ESP_STAT_PERR)) {
-				message_out = MSG_PARITY_ERROR;
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-			} else if((it = (esp_read(eregs->esp_fflags) & ESP_FF_FBYTES))!=1) {
-				/* We certainly dropped the ball somewhere. */
-				message_out = INITIATOR_ERROR;
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-			} else if(!esp->msgin_len) {
-				it = esp_read(eregs->esp_fdata);
-				esp_advance_phase(SCptr, in_msgincont);
-			} else {
-				/* it is ok and we want it */
-				it = esp->cur_msgin[esp->msgin_ctr] =
-					esp_read(eregs->esp_fdata);
-				esp->msgin_ctr++;
-			}
-		} else {
-			esp_advance_phase(SCptr, in_the_dark);
-			return do_work_bus;
-		}
-	} else {
-		it = esp->cur_msgin[0];
-	}
-	if(!message_out && esp->msgin_len) {
-		if(esp->msgin_ctr < esp->msgin_len) {
-			esp_advance_phase(SCptr, in_msgincont);
-		} else if(esp->msgin_len == 1) {
-			message_out = check_singlebyte_msg(esp, eregs);
-		} else if(esp->msgin_len == 2) {
-			if(esp->cur_msgin[0] == EXTENDED_MESSAGE) {
-				if((it+2) >= 15) {
-					message_out = MESSAGE_REJECT;
-				} else {
-					esp->msgin_len = (it + 2);
-					esp_advance_phase(SCptr, in_msgincont);
-				}
-			} else {
-				message_out = MESSAGE_REJECT; /* foo on you */
-			}
-		} else {
-			message_out = check_multibyte_msg(esp, eregs);
-		}
-	}
-	if(message_out < 0) {
-		return -message_out;
-	} else if(message_out) {
-		if(((message_out != 1) &&
-		    ((message_out < 0x20) || (message_out & 0x80))))
-			esp->msgout_len = 1;
-		esp->cur_msgout[0] = message_out;
-		esp_cmd(esp, eregs, ESP_CMD_SATN);
-		esp_advance_phase(SCptr, in_the_dark);
-		esp->msgin_len = 0;
-	}
-	esp->sreg = esp_read(eregs->esp_status);
-	esp->sreg &= ~(ESP_STAT_INTR);
-	if((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD))
-		esp_cmd(esp, eregs, ESP_CMD_MOK);
-	if((SCptr->SCp.sent_command == in_msgindone) &&
-	    (SCptr->SCp.phase == in_freeing))
-		return esp_do_freebus(esp, eregs);
-	return do_intr_end;
-}
-
-static int esp_do_cmdbegin(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	unsigned char tmp;
-	Scsi_Cmnd *SCptr = esp->current_SC;
-
-	esp_advance_phase(SCptr, in_cmdend);
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	tmp = *esp->esp_scmdp++;
-	esp->esp_scmdleft--;
-	esp_write(eregs->esp_fdata, tmp);
-	esp_cmd(esp, eregs, ESP_CMD_TI);
-	return do_intr_end;
-}
-
-static int esp_do_cmddone(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	esp_cmd(esp, eregs, ESP_CMD_NULL);
-	if(esp->ireg & ESP_INTR_BSERV) {
-		esp_advance_phase(esp->current_SC, in_the_dark);
-		return esp_do_phase_determine(esp, eregs);
-	}
-	ESPLOG(("esp%d: in do_cmddone() but didn't get BSERV interrupt.\n",
-		esp->esp_id));
-	return do_reset_bus;
-}
-
-static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	switch(esp->msgout_len) {
-	case 1:
-		esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
-		esp_cmd(esp, eregs, ESP_CMD_TI);
-		break;
-
-	case 2:
-		if(esp->do_pio_cmds){
-			esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[1]);
-			esp_cmd(esp, eregs, ESP_CMD_TI);
-		} else {
-			esp->esp_command[0] = esp->cur_msgout[0];
-			esp->esp_command[1] = esp->cur_msgout[1];
-			esp->dma_setup(esp, esp->esp_command_dvma, 2, 0);
-			esp_setcount(eregs, 2);
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-		}
-		break;
-
-	case 4:
-		esp->snip = 1;
-		if(esp->do_pio_cmds){
-			esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[1]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[2]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[3]);
-			esp_cmd(esp, eregs, ESP_CMD_TI);
-		} else {
-			esp->esp_command[0] = esp->cur_msgout[0];
-			esp->esp_command[1] = esp->cur_msgout[1];
-			esp->esp_command[2] = esp->cur_msgout[2];
-			esp->esp_command[3] = esp->cur_msgout[3];
-			esp->dma_setup(esp, esp->esp_command_dvma, 4, 0);
-			esp_setcount(eregs, 4);
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-		}
-		break;
-
-	case 5:
-		esp->snip = 1;
-		if(esp->do_pio_cmds){
-			esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[1]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[2]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[3]);
-			esp_write(eregs->esp_fdata, esp->cur_msgout[4]);
-			esp_cmd(esp, eregs, ESP_CMD_TI);
-		} else {
-			esp->esp_command[0] = esp->cur_msgout[0];
-			esp->esp_command[1] = esp->cur_msgout[1];
-			esp->esp_command[2] = esp->cur_msgout[2];
-			esp->esp_command[3] = esp->cur_msgout[3];
-			esp->esp_command[4] = esp->cur_msgout[4];
-			esp->dma_setup(esp, esp->esp_command_dvma, 5, 0);
-			esp_setcount(eregs, 5);
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-		}
-		break;
-
-	default:
-		/* whoops */
-		ESPMISC(("bogus msgout sending NOP\n"));
-		esp->cur_msgout[0] = NOP;
-		esp_write(eregs->esp_fdata, esp->cur_msgout[0]);
-		esp->msgout_len = 1;
-		esp_cmd(esp, eregs, ESP_CMD_TI);
-		break;
-	}
-	esp_advance_phase(esp->current_SC, in_msgoutdone);
-	return do_intr_end;
-}
-
-static int esp_do_msgoutdone(struct NCR_ESP *esp, 
-			     struct ESP_regs *eregs)
-{
-	if((esp->msgout_len > 1) && esp->dma_barrier)
-		esp->dma_barrier(esp);
-
-	if(!(esp->ireg & ESP_INTR_DC)) {
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
-		switch(esp->sreg & ESP_STAT_PMASK) {
-		case ESP_MOP:
-			/* whoops, parity error */
-			ESPLOG(("esp%d: still in msgout, parity error assumed\n",
-				esp->esp_id));
-			if(esp->msgout_len > 1)
-				esp_cmd(esp, eregs, ESP_CMD_SATN);
-			esp_advance_phase(esp->current_SC, in_msgout);
-			return do_work_bus;
-
-		case ESP_DIP:
-			break;
-
-		default:
-			if(!fcount(esp, eregs) &&
-			   !(((struct esp_device *)esp->current_SC->device->hostdata)->sync_max_offset))
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-			break;
-
-		};
-	}
-
-	/* If we sent out a synchronous negotiation message, update
-	 * our state.
-	 */
-	if(esp->cur_msgout[2] == EXTENDED_MESSAGE &&
-	   esp->cur_msgout[4] == EXTENDED_SDTR) {
-		esp->snip = 1; /* anal retentiveness... */
-	}
-
-	esp->prevmsgout = esp->cur_msgout[0];
-	esp->msgout_len = 0;
-	esp_advance_phase(esp->current_SC, in_the_dark);
-	return esp_do_phase_determine(esp, eregs);
-}
-
-static int esp_bus_unexpected(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	ESPLOG(("esp%d: command in weird state %2x\n",
-		esp->esp_id, esp->current_SC->SCp.phase));
-	return do_reset_bus;
-}
-
-static espfunc_t bus_vector[] = {
-	esp_do_data_finale,
-	esp_do_data_finale,
-	esp_bus_unexpected,
-	esp_do_msgin,
-	esp_do_msgincont,
-	esp_do_msgindone,
-	esp_do_msgout,
-	esp_do_msgoutdone,
-	esp_do_cmdbegin,
-	esp_do_cmddone,
-	esp_do_status,
-	esp_do_freebus,
-	esp_do_phase_determine,
-	esp_bus_unexpected,
-	esp_bus_unexpected,
-	esp_bus_unexpected,
-};
-
-/* This is the second tier in our dual-level SCSI state machine. */
-static int esp_work_bus(struct NCR_ESP *esp, struct ESP_regs *eregs)
-{
-	Scsi_Cmnd *SCptr = esp->current_SC;
-	unsigned int phase;
-
-	ESPBUS(("esp_work_bus: "));
-	if(!SCptr) {
-		ESPBUS(("reconnect\n"));
-		return esp_do_reconnect(esp, eregs);
-	}
-	phase = SCptr->SCp.phase;
-	if ((phase & 0xf0) == in_phases_mask)
-		return bus_vector[(phase & 0x0f)](esp, eregs);
-	else if((phase & 0xf0) == in_slct_mask)
-		return esp_select_complete(esp, eregs);
-	else
-		return esp_bus_unexpected(esp, eregs);
-}
-
-static espfunc_t isvc_vector[] = {
-	NULL,
-	esp_do_phase_determine,
-	esp_do_resetbus,
-	esp_finish_reset,
-	esp_work_bus
-};
-
-/* Main interrupt handler for an esp adapter. */
-void esp_handle(struct NCR_ESP *esp)
-{
-	struct ESP_regs *eregs;
-	Scsi_Cmnd *SCptr;
-	int what_next = do_intr_end;
-	eregs = esp->eregs;
-	SCptr = esp->current_SC;
-
-	if(esp->dma_irq_entry)
-		esp->dma_irq_entry(esp);
-
-	/* Check for errors. */
-	esp->sreg = esp_read(eregs->esp_status);
-	esp->sreg &= (~ESP_STAT_INTR);
-	esp->seqreg = (esp_read(eregs->esp_sstep) & ESP_STEP_VBITS);
-	esp->ireg = esp_read(eregs->esp_intrpt);   /* Unlatch intr and stat regs */
-	ESPIRQ(("handle_irq: [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
-		esp->sreg, esp->seqreg, esp->ireg));
-	if(esp->sreg & (ESP_STAT_SPAM)) {
-		/* Gross error, could be due to one of:
-		 *
-		 * - top of fifo overwritten, could be because
-		 *   we tried to do a synchronous transfer with
-		 *   an offset greater than ESP fifo size
-		 *
-		 * - top of command register overwritten
-		 *
-		 * - DMA setup to go in one direction, SCSI
-		 *   bus points in the other, whoops
-		 *
-		 * - weird phase change during asynchronous
-		 *   data phase while we are initiator
-		 */
-		ESPLOG(("esp%d: Gross error sreg=%2x\n", esp->esp_id, esp->sreg));
-
-		/* If a command is live on the bus we cannot safely
-		 * reset the bus, so we'll just let the pieces fall
-		 * where they may.  Here we are hoping that the
-		 * target will be able to cleanly go away soon
-		 * so we can safely reset things.
-		 */
-		if(!SCptr) {
-			ESPLOG(("esp%d: No current cmd during gross error, "
-				"resetting bus\n", esp->esp_id));
-			what_next = do_reset_bus;
-			goto state_machine;
-		}
-	}
-
-	/* No current cmd is only valid at this point when there are
-	 * commands off the bus or we are trying a reset.
-	 */
-	if(!SCptr && !esp->disconnected_SC && !(esp->ireg & ESP_INTR_SR)) {
-		/* Panic is safe, since current_SC is null. */
-		ESPLOG(("esp%d: no command in esp_handle()\n", esp->esp_id));
-		panic("esp_handle: current_SC == penguin within interrupt!");
-	}
-
-	if(esp->ireg & (ESP_INTR_IC)) {
-		/* Illegal command fed to ESP.  Outside of obvious
-		 * software bugs that could cause this, there is
-		 * a condition with ESP100 where we can confuse the
-		 * ESP into an erroneous illegal command interrupt
-		 * because it does not scrape the FIFO properly
-		 * for reselection.  See esp100_reconnect_hwbug()
-		 * to see how we try very hard to avoid this.
-		 */
-		ESPLOG(("esp%d: invalid command\n", esp->esp_id));
-
-		esp_dump_state(esp, eregs);
-
-		if(SCptr) {
-			/* Devices with very buggy firmware can drop BSY
-			 * during a scatter list interrupt when using sync
-			 * mode transfers.  We continue the transfer as
-			 * expected, the target drops the bus, the ESP
-			 * gets confused, and we get a illegal command
-			 * interrupt because the bus is in the disconnected
-			 * state now and ESP_CMD_TI is only allowed when
-			 * a nexus is alive on the bus.
-			 */
-			ESPLOG(("esp%d: Forcing async and disabling disconnect for "
-				"target %d\n", esp->esp_id, SCptr->device->id));
-			SCptr->device->borken = 1; /* foo on you */
-		}
-
-		what_next = do_reset_bus;
-	} else if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
-		int phase;
-
-		if(SCptr) {
-			phase = SCptr->SCp.phase;
-			if(phase & in_phases_mask) {
-				what_next = esp_work_bus(esp, eregs);
-			} else if(phase & in_slct_mask) {
-				what_next = esp_select_complete(esp, eregs);
-			} else {
-				ESPLOG(("esp%d: interrupt for no good reason...\n",
-					esp->esp_id));
-				what_next = do_intr_end;
-			}
-		} else {
-			ESPLOG(("esp%d: BSERV or FDONE or DC while SCptr==NULL\n",
-				esp->esp_id));
-			what_next = do_reset_bus;
-		}
-	} else if(esp->ireg & ESP_INTR_SR) {
-		ESPLOG(("esp%d: SCSI bus reset interrupt\n", esp->esp_id));
-		what_next = do_reset_complete;
-	} else if(esp->ireg & (ESP_INTR_S | ESP_INTR_SATN)) {
-		ESPLOG(("esp%d: AIEEE we have been selected by another initiator!\n",
-			esp->esp_id));
-		what_next = do_reset_bus;
-	} else if(esp->ireg & ESP_INTR_RSEL) {
-		if(!SCptr) {
-			/* This is ok. */
-			what_next = esp_do_reconnect(esp, eregs);
-		} else if(SCptr->SCp.phase & in_slct_mask) {
-			/* Only selection code knows how to clean
-			 * up properly.
-			 */
-			ESPDISC(("Reselected during selection attempt\n"));
-			what_next = esp_select_complete(esp, eregs);
-		} else {
-			ESPLOG(("esp%d: Reselected while bus is busy\n",
-				esp->esp_id));
-			what_next = do_reset_bus;
-		}
-	}
-
-	/* This is tier-one in our dual level SCSI state machine. */
-state_machine:
-	while(what_next != do_intr_end) {
-		if (what_next >= do_phase_determine &&
-		    what_next < do_intr_end)
-			what_next = isvc_vector[what_next](esp, eregs);
-		else {
-			/* state is completely lost ;-( */
-			ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n",
-				esp->esp_id));
-			what_next = do_reset_bus;
-		}
-	}
-	if(esp->dma_irq_exit)
-		esp->dma_irq_exit(esp);
-}
-EXPORT_SYMBOL(esp_handle);
-
-#ifndef CONFIG_SMP
-irqreturn_t esp_intr(int irq, void *dev_id)
-{
-	struct NCR_ESP *esp;
-	unsigned long flags;
-	int again;
-	struct Scsi_Host *dev = dev_id;
-
-	/* Handle all ESP interrupts showing at this IRQ level. */
-	spin_lock_irqsave(dev->host_lock, flags);
-repeat:
-	again = 0;
-	for_each_esp(esp) {
-#ifndef __mips__	    
-		if(((esp)->irq & 0xff) == irq) {
-#endif		    
-			if(esp->dma_irq_p(esp)) {
-				again = 1;
-
-				esp->dma_ints_off(esp);
-
-				ESPIRQ(("I%d(", esp->esp_id));
-				esp_handle(esp);
-				ESPIRQ((")"));
-
-				esp->dma_ints_on(esp);
-			}
-#ifndef __mips__		    
-		}
-#endif	    
-	}
-	if(again)
-		goto repeat;
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-#else
-/* For SMP we only service one ESP on the list list at our IRQ level! */
-irqreturn_t esp_intr(int irq, void *dev_id)
-{
-	struct NCR_ESP *esp;
-	unsigned long flags;
-	struct Scsi_Host *dev = dev_id;
-	
-	/* Handle all ESP interrupts showing at this IRQ level. */
-	spin_lock_irqsave(dev->host_lock, flags);
-	for_each_esp(esp) {
-		if(((esp)->irq & 0xf) == irq) {
-			if(esp->dma_irq_p(esp)) {
-				esp->dma_ints_off(esp);
-
-				ESPIRQ(("I[%d:%d](",
-					smp_processor_id(), esp->esp_id));
-				esp_handle(esp);
-				ESPIRQ((")"));
-
-				esp->dma_ints_on(esp);
-				goto out;
-			}
-		}
-	}
-out:
-	spin_unlock_irqrestore(dev->host_lock, flags);
-	return IRQ_HANDLED;
-}
-#endif
-
-int esp_slave_alloc(struct scsi_device *SDptr)
-{
-	struct esp_device *esp_dev =
-		kzalloc(sizeof(struct esp_device), GFP_ATOMIC);
-
-	if (!esp_dev)
-		return -ENOMEM;
-	SDptr->hostdata = esp_dev;
-	return 0;
-}
-
-void esp_slave_destroy(struct scsi_device *SDptr)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata;
-
-	esp->targets_present &= ~(1 << sdev_id(SDptr));
-	kfree(SDptr->hostdata);
-	SDptr->hostdata = NULL;
-}
-
-#ifdef MODULE
-int init_module(void) { return 0; }
-void cleanup_module(void) {}
-void esp_release(void)
-{
-	esps_in_use--;
-	esps_running = esps_in_use;
-}
-EXPORT_SYMBOL(esp_release);
-#endif
-
-EXPORT_SYMBOL(esp_abort);
-EXPORT_SYMBOL(esp_allocate);
-EXPORT_SYMBOL(esp_deallocate);
-EXPORT_SYMBOL(esp_initialize);
-EXPORT_SYMBOL(esp_intr);
-EXPORT_SYMBOL(esp_queue);
-EXPORT_SYMBOL(esp_reset);
-EXPORT_SYMBOL(esp_slave_alloc);
-EXPORT_SYMBOL(esp_slave_destroy);
-EXPORT_SYMBOL(esps_in_use);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h
deleted file mode 100644
index 00a0ba0..0000000
--- a/drivers/scsi/NCR53C9x.h
+++ /dev/null
@@ -1,668 +0,0 @@
-/* NCR53C9x.c:  Defines and structures for the NCR53C9x generic driver.
- *
- * Originally esp.h:  Defines and structures for the Sparc ESP 
- *                   (Enhanced SCSI Processor) driver under Linux.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- * Generalization by Jesper Skov (jskov@cygnus.co.uk)
- *
- * More generalization (for i386 stuff) by Tymm Twillman (tymm@computer.org)
- */
-
-#ifndef NCR53C9X_H
-#define NCR53C9X_H
-
-#include <linux/interrupt.h>
-
-/* djweis for mac driver */
-#if defined(CONFIG_MAC)
-#define PAD_SIZE 15
-#else
-#define PAD_SIZE 3
-#endif
-
-/* Handle multiple hostadapters on Amiga
- * generally PAD_SIZE = 3
- * but there is one exception: Oktagon (PAD_SIZE = 1) */
-#if defined(CONFIG_OKTAGON_SCSI) || defined(CONFIG_OKTAGON_SCSI_MODULE)
-#undef PAD_SIZE
-#if defined(CONFIG_BLZ1230_SCSI) || defined(CONFIG_BLZ1230_SCSI_MODULE) || \
-    defined(CONFIG_BLZ2060_SCSI) || defined(CONFIG_BLZ2060_SCSI_MODULE) || \
-    defined(CONFIG_CYBERSTORM_SCSI) || defined(CONFIG_CYBERSTORM_SCSI_MODULE) || \
-    defined(CONFIG_CYBERSTORMII_SCSI) || defined(CONFIG_CYBERSTORMII_SCSI_MODULE) || \
-    defined(CONFIG_FASTLANE_SCSI) || defined(CONFIG_FASTLANE_SCSI_MODULE)
-#define MULTIPLE_PAD_SIZES
-#else
-#define PAD_SIZE 1
-#endif
-#endif
-
-/* Macros for debugging messages */
-
-#define DEBUG_ESP
-/* #define DEBUG_ESP_DATA */
-/* #define DEBUG_ESP_QUEUE */
-/* #define DEBUG_ESP_DISCONNECT */
-/* #define DEBUG_ESP_STATUS */
-/* #define DEBUG_ESP_PHASES */
-/* #define DEBUG_ESP_WORKBUS */
-/* #define DEBUG_STATE_MACHINE */
-/* #define DEBUG_ESP_CMDS */
-/* #define DEBUG_ESP_IRQS */
-/* #define DEBUG_SDTR */
-/* #define DEBUG_ESP_SG */
-
-/* Use the following to sprinkle debugging messages in a way which
- * suits you if combinations of the above become too verbose when
- * trying to track down a specific problem.
- */
-/* #define DEBUG_ESP_MISC */
-
-#if defined(DEBUG_ESP)
-#define ESPLOG(foo)  printk foo
-#else
-#define ESPLOG(foo)
-#endif /* (DEBUG_ESP) */
-
-#if defined(DEBUG_ESP_DATA)
-#define ESPDATA(foo)  printk foo
-#else
-#define ESPDATA(foo)
-#endif
-
-#if defined(DEBUG_ESP_QUEUE)
-#define ESPQUEUE(foo)  printk foo
-#else
-#define ESPQUEUE(foo)
-#endif
-
-#if defined(DEBUG_ESP_DISCONNECT)
-#define ESPDISC(foo)  printk foo
-#else
-#define ESPDISC(foo)
-#endif
-
-#if defined(DEBUG_ESP_STATUS)
-#define ESPSTAT(foo)  printk foo
-#else
-#define ESPSTAT(foo)
-#endif
-
-#if defined(DEBUG_ESP_PHASES)
-#define ESPPHASE(foo)  printk foo
-#else
-#define ESPPHASE(foo)
-#endif
-
-#if defined(DEBUG_ESP_WORKBUS)
-#define ESPBUS(foo)  printk foo
-#else
-#define ESPBUS(foo)
-#endif
-
-#if defined(DEBUG_ESP_IRQS)
-#define ESPIRQ(foo)  printk foo
-#else
-#define ESPIRQ(foo)
-#endif
-
-#if defined(DEBUG_SDTR)
-#define ESPSDTR(foo)  printk foo
-#else
-#define ESPSDTR(foo)
-#endif
-
-#if defined(DEBUG_ESP_MISC)
-#define ESPMISC(foo)  printk foo
-#else
-#define ESPMISC(foo)
-#endif
-
-/*
- * padding for register structure
- */
-#ifdef CONFIG_JAZZ_ESP
-#define EREGS_PAD(n)
-#else
-#ifndef MULTIPLE_PAD_SIZES
-#define EREGS_PAD(n)    unchar n[PAD_SIZE];
-#endif
-#endif
-
-/* The ESP SCSI controllers have their register sets in three
- * "classes":
- *
- * 1) Registers which are both read and write.
- * 2) Registers which are read only.
- * 3) Registers which are write only.
- *
- * Yet, they all live within the same IO space.
- */
-
-#if !defined(__i386__) && !defined(__x86_64__)
-
-#ifndef MULTIPLE_PAD_SIZES
-
-#ifdef CONFIG_CPU_HAS_WB
-#include <asm/wbflush.h>
-#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
-#else
-#define esp_write(__reg, __val) ((__reg) = (__val))
-#endif
-#define esp_read(__reg) (__reg)
-
-struct ESP_regs {
-                                /* Access    Description              Offset */
-    volatile unchar esp_tclow;  /* rw  Low bits of the transfer count 0x00   */
-                                EREGS_PAD(tlpad1);
-    volatile unchar esp_tcmed;  /* rw  Mid bits of the transfer count 0x04   */
-                                EREGS_PAD(fdpad);
-    volatile unchar esp_fdata;  /* rw  FIFO data bits                 0x08   */
-                                EREGS_PAD(cbpad);
-    volatile unchar esp_cmnd;   /* rw  SCSI command bits              0x0c   */
-                                EREGS_PAD(stpad);
-    volatile unchar esp_status; /* ro  ESP status register            0x10   */
-#define esp_busid   esp_status  /* wo  Bus ID for select/reselect     0x10   */
-                                EREGS_PAD(irqpd);
-    volatile unchar esp_intrpt; /* ro  Kind of interrupt              0x14   */
-#define esp_timeo   esp_intrpt  /* wo  Timeout value for select/resel 0x14   */
-                                EREGS_PAD(sspad);
-    volatile unchar esp_sstep;  /* ro  Sequence step register         0x18   */
-#define esp_stp     esp_sstep   /* wo  Transfer period per sync       0x18   */
-                                EREGS_PAD(ffpad);
-    volatile unchar esp_fflags; /* ro  Bits of current FIFO info      0x1c   */
-#define esp_soff    esp_fflags  /* wo  Sync offset                    0x1c   */
-                                EREGS_PAD(cf1pd);
-    volatile unchar esp_cfg1;   /* rw  First configuration register   0x20   */
-                                EREGS_PAD(cfpad);
-    volatile unchar esp_cfact;  /* wo  Clock conversion factor        0x24   */
-                                EREGS_PAD(ctpad);
-    volatile unchar esp_ctest;  /* wo  Chip test register             0x28   */
-                                EREGS_PAD(cf2pd);
-    volatile unchar esp_cfg2;   /* rw  Second configuration register  0x2c   */
-                                EREGS_PAD(cf3pd);
-
-    /* The following is only found on the 53C9X series SCSI chips */
-    volatile unchar esp_cfg3;   /* rw  Third configuration register   0x30  */
-                                EREGS_PAD(cf4pd);
-    volatile unchar esp_cfg4;   /* rw  Fourth configuration register  0x34  */
-                                EREGS_PAD(thpd);
-    /* The following is found on all chips except the NCR53C90 (ESP100) */
-    volatile unchar esp_tchi;   /* rw  High bits of transfer count    0x38  */
-#define esp_uid     esp_tchi    /* ro  Unique ID code                 0x38  */
-                                EREGS_PAD(fgpad);    
-    volatile unchar esp_fgrnd;  /* rw  Data base for fifo             0x3c  */
-};
-
-#else /* MULTIPLE_PAD_SIZES */
-
-#define esp_write(__reg, __val) (*(__reg) = (__val))
-#define esp_read(__reg) (*(__reg))
-
-struct ESP_regs {
-    unsigned char io_addr[64]; /* dummy */
-                                                 /* Access    Description              Offset */
-#define esp_tclow   io_addr                      /* rw  Low bits of the transfer count 0x00   */
-#define esp_tcmed   io_addr + (1<<(esp->shift))  /* rw  Mid bits of the transfer count 0x04   */
-#define esp_fdata   io_addr + (2<<(esp->shift))  /* rw  FIFO data bits                 0x08   */
-#define esp_cmnd    io_addr + (3<<(esp->shift))  /* rw  SCSI command bits              0x0c   */
-#define esp_status  io_addr + (4<<(esp->shift))  /* ro  ESP status register            0x10   */
-#define esp_busid   esp_status                   /* wo  Bus ID for select/reselect     0x10   */
-#define esp_intrpt  io_addr + (5<<(esp->shift))  /* ro  Kind of interrupt              0x14   */
-#define esp_timeo   esp_intrpt                   /* wo  Timeout value for select/resel 0x14   */
-#define esp_sstep   io_addr + (6<<(esp->shift))  /* ro  Sequence step register         0x18   */
-#define esp_stp     esp_sstep                    /* wo  Transfer period per sync       0x18   */
-#define esp_fflags  io_addr + (7<<(esp->shift))  /* ro  Bits of current FIFO info      0x1c   */
-#define esp_soff    esp_fflags                   /* wo  Sync offset                    0x1c   */
-#define esp_cfg1    io_addr + (8<<(esp->shift))  /* rw  First configuration register   0x20   */
-#define esp_cfact   io_addr + (9<<(esp->shift))  /* wo  Clock conversion factor        0x24   */
-#define esp_ctest   io_addr + (10<<(esp->shift)) /* wo  Chip test register             0x28   */
-#define esp_cfg2    io_addr + (11<<(esp->shift)) /* rw  Second configuration register  0x2c   */
-
-    /* The following is only found on the 53C9X series SCSI chips */
-#define esp_cfg3    io_addr + (12<<(esp->shift)) /* rw  Third configuration register   0x30  */
-#define esp_cfg4    io_addr + (13<<(esp->shift)) /* rw  Fourth configuration register  0x34  */
-
-    /* The following is found on all chips except the NCR53C90 (ESP100) */
-#define esp_tchi    io_addr + (14<<(esp->shift)) /* rw  High bits of transfer count    0x38  */
-#define esp_uid     esp_tchi                     /* ro  Unique ID code                 0x38  */
-#define esp_fgrnd   io_addr + (15<<(esp->shift)) /* rw  Data base for fifo             0x3c  */
-};
-
-#endif
-
-#else /* !defined(__i386__) && !defined(__x86_64__) */
-
-#define esp_write(__reg, __val) outb((__val), (__reg))
-#define esp_read(__reg) inb((__reg))
-
-struct ESP_regs {
-    unsigned int io_addr;
-                                 /* Access    Description              Offset */
-#define esp_tclow   io_addr      /* rw  Low bits of the transfer count 0x00   */
-#define esp_tcmed   io_addr + 1  /* rw  Mid bits of the transfer count 0x04   */
-#define esp_fdata   io_addr + 2  /* rw  FIFO data bits                 0x08   */
-#define esp_cmnd    io_addr + 3  /* rw  SCSI command bits              0x0c   */
-#define esp_status  io_addr + 4  /* ro  ESP status register            0x10   */
-#define esp_busid   esp_status   /* wo  Bus ID for select/reselect     0x10   */
-#define esp_intrpt  io_addr + 5  /* ro  Kind of interrupt              0x14   */
-#define esp_timeo   esp_intrpt   /* wo  Timeout value for select/resel 0x14   */
-#define esp_sstep   io_addr + 6  /* ro  Sequence step register         0x18   */
-#define esp_stp     esp_sstep    /* wo  Transfer period per sync       0x18   */
-#define esp_fflags  io_addr + 7  /* ro  Bits of current FIFO info      0x1c   */
-#define esp_soff    esp_fflags   /* wo  Sync offset                    0x1c   */
-#define esp_cfg1    io_addr + 8  /* rw  First configuration register   0x20   */
-#define esp_cfact   io_addr + 9  /* wo  Clock conversion factor        0x24   */
-#define esp_ctest   io_addr + 10 /* wo  Chip test register             0x28   */
-#define esp_cfg2    io_addr + 11 /* rw  Second configuration register  0x2c   */
-
-    /* The following is only found on the 53C9X series SCSI chips */
-#define esp_cfg3    io_addr + 12 /* rw  Third configuration register   0x30  */
-#define esp_cfg4    io_addr + 13 /* rw  Fourth configuration register  0x34  */
-
-    /* The following is found on all chips except the NCR53C90 (ESP100) */
-#define esp_tchi    io_addr + 14 /* rw  High bits of transfer count    0x38  */
-#define esp_uid     esp_tchi     /* ro  Unique ID code                 0x38  */
-#define esp_fgrnd   io_addr + 15 /* rw  Data base for fifo             0x3c  */
-};
-
-#endif /* !defined(__i386__) && !defined(__x86_64__) */
-
-/* Various revisions of the ESP board. */
-enum esp_rev {
-  esp100     = 0x00,  /* NCR53C90 - very broken */
-  esp100a    = 0x01,  /* NCR53C90A */
-  esp236     = 0x02,
-  fas236     = 0x03,
-  fas100a    = 0x04,
-  fast       = 0x05,
-  fas366     = 0x06,
-  fas216     = 0x07,
-  fsc        = 0x08,  /* SYM53C94-2 */
-  espunknown = 0x09
-};
-
-/* We allocate one of these for each scsi device and attach it to
- * SDptr->hostdata for use in the driver
- */
-struct esp_device {
-  unsigned char sync_min_period;
-  unsigned char sync_max_offset;
-  unsigned sync:1;
-  unsigned wide:1;
-  unsigned disconnect:1;
-};
-
-/* We get one of these for each ESP probed. */
-struct NCR_ESP {
-  struct NCR_ESP *next;                   /* Next ESP on probed or NULL */
-  struct ESP_regs *eregs;	          /* All esp registers */
-  int dma;                                /* Who I do transfers with. */
-  void *dregs;		  		  /* And his registers. */
-  struct Scsi_Host *ehost;                /* Backpointer to SCSI Host */
-
-  void *edev;        		          /* Pointer to controller base/SBus */
-  int esp_id;                             /* Unique per-ESP ID number */
-
-  /* ESP Configuration Registers */
-  unsigned char config1;                  /* Copy of the 1st config register */
-  unsigned char config2;                  /* Copy of the 2nd config register */
-  unsigned char config3[16];              /* Copy of the 3rd config register */
-
-  /* The current command we are sending to the ESP chip.  This esp_command
-   * ptr needs to be mapped in DVMA area so we can send commands and read
-   * from the ESP fifo without burning precious CPU cycles.  Programmed I/O
-   * sucks when we have the DVMA to do it for us.  The ESP is stupid and will
-   * only send out 6, 10, and 12 byte SCSI commands, others we need to send
-   * one byte at a time.  esp_slowcmd being set says that we are doing one
-   * of the command types ESP doesn't understand, esp_scmdp keeps track of
-   * which byte we are sending, esp_scmdleft says how many bytes to go.
-   */
-  volatile unchar *esp_command;           /* Location of command (CPU view)  */
-  __u32            esp_command_dvma;      /* Location of command (DVMA view) */
-  unsigned char esp_clen;                 /* Length of this command */
-  unsigned char esp_slowcmd;
-  unsigned char *esp_scmdp;
-  unsigned char esp_scmdleft;
-
-  /* The following are used to determine the cause of an IRQ. Upon every
-   * IRQ entry we synchronize these with the hardware registers.
-   */
-  unchar ireg;                            /* Copy of ESP interrupt register */
-  unchar sreg;                            /* Same for ESP status register */
-  unchar seqreg;                          /* The ESP sequence register */
-
-  /* The following is set when a premature interrupt condition is detected
-   * in some FAS revisions.
-   */
-  unchar fas_premature_intr_workaround;
-
-  /* To save register writes to the ESP, which can be expensive, we
-   * keep track of the previous value that various registers had for
-   * the last target we connected to.  If they are the same for the
-   * current target, we skip the register writes as they are not needed.
-   */
-  unchar prev_soff, prev_stp, prev_cfg3;
-
-  /* For each target we keep track of save/restore data
-   * pointer information.  This needs to be updated majorly
-   * when we add support for tagged queueing.  -DaveM
-   */
-  struct esp_pointers {
-	  char *saved_ptr;
-	  struct scatterlist *saved_buffer;
-	  int saved_this_residual;
-	  int saved_buffers_residual;
-  } data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/;
-
-  /* Clock periods, frequencies, synchronization, etc. */
-  unsigned int cfreq;                    /* Clock frequency in HZ */
-  unsigned int cfact;                    /* Clock conversion factor */
-  unsigned int ccycle;                   /* One ESP clock cycle */
-  unsigned int ctick;                    /* One ESP clock time */
-  unsigned int radelay;                  /* FAST chip req/ack delay */
-  unsigned int neg_defp;                 /* Default negotiation period */
-  unsigned int sync_defp;                /* Default sync transfer period */
-  unsigned int max_period;               /* longest our period can be */
-  unsigned int min_period;               /* shortest period we can withstand */
-  /* For slow to medium speed input clock rates we shoot for 5mb/s,
-   * but for high input clock rates we try to do 10mb/s although I
-   * don't think a transfer can even run that fast with an ESP even
-   * with DMA2 scatter gather pipelining.
-   */
-#define SYNC_DEFP_SLOW            0x32   /* 5mb/s  */
-#define SYNC_DEFP_FAST            0x19   /* 10mb/s */
-
-  unsigned int snip;                      /* Sync. negotiation in progress */
-  unsigned int wnip;                      /* WIDE negotiation in progress */
-  unsigned int targets_present;           /* targets spoken to before */
-
-  int current_transfer_size;              /* Set at beginning of data dma */
-
-  unchar espcmdlog[32];                   /* Log of current esp cmds sent. */
-  unchar espcmdent;                       /* Current entry in esp cmd log. */
-
-  /* Misc. info about this ESP */
-  enum esp_rev erev;                      /* ESP revision */
-  int irq;                                /* IRQ for this ESP */
-  int scsi_id;                            /* Who am I as initiator? */
-  int scsi_id_mask;                       /* Bitmask of 'me'. */
-  int diff;                               /* Differential SCSI bus? */
-  int slot;                               /* Slot the adapter occupies */
-
-  /* Our command queues, only one cmd lives in the current_SC queue. */
-  Scsi_Cmnd *issue_SC;           /* Commands to be issued */
-  Scsi_Cmnd *current_SC;         /* Who is currently working the bus */
-  Scsi_Cmnd *disconnected_SC;    /* Commands disconnected from the bus */
-
-  /* Message goo */
-  unchar cur_msgout[16];
-  unchar cur_msgin[16];
-  unchar prevmsgout, prevmsgin;
-  unchar msgout_len, msgin_len;
-  unchar msgout_ctr, msgin_ctr;
-
-  /* States that we cannot keep in the per cmd structure because they
-   * cannot be assosciated with any specific command.
-   */
-  unchar resetting_bus;
-  wait_queue_head_t reset_queue;
-
-  unchar do_pio_cmds;		/* Do command transfer with pio */
-
-  /* How much bits do we have to shift the registers */
-  unsigned char shift;
-
-  /* Functions handling DMA
-   */ 
-  /* Required functions */
-  int  (*dma_bytes_sent)(struct NCR_ESP *, int);
-  int  (*dma_can_transfer)(struct NCR_ESP *, Scsi_Cmnd *);
-  void (*dma_dump_state)(struct NCR_ESP *);
-  void (*dma_init_read)(struct NCR_ESP *, __u32, int);
-  void (*dma_init_write)(struct NCR_ESP *, __u32, int);
-  void (*dma_ints_off)(struct NCR_ESP *);
-  void (*dma_ints_on)(struct NCR_ESP *);
-  int  (*dma_irq_p)(struct NCR_ESP *);
-  int  (*dma_ports_p)(struct NCR_ESP *);
-  void (*dma_setup)(struct NCR_ESP *, __u32, int, int);
-
-  /* Optional functions (i.e. may be initialized to 0) */
-  void (*dma_barrier)(struct NCR_ESP *);
-  void (*dma_drain)(struct NCR_ESP *);
-  void (*dma_invalidate)(struct NCR_ESP *);
-  void (*dma_irq_entry)(struct NCR_ESP *);
-  void (*dma_irq_exit)(struct NCR_ESP *);
-  void (*dma_led_off)(struct NCR_ESP *);
-  void (*dma_led_on)(struct NCR_ESP *);
-  void (*dma_poll)(struct NCR_ESP *, unsigned char *);
-  void (*dma_reset)(struct NCR_ESP *);
-    
-  /* Optional virtual DMA functions */
-  void (*dma_mmu_get_scsi_one)(struct NCR_ESP *, Scsi_Cmnd *);
-  void (*dma_mmu_get_scsi_sgl)(struct NCR_ESP *, Scsi_Cmnd *);
-  void (*dma_mmu_release_scsi_one)(struct NCR_ESP *, Scsi_Cmnd *);
-  void (*dma_mmu_release_scsi_sgl)(struct NCR_ESP *, Scsi_Cmnd *);
-  void (*dma_advance_sg)(Scsi_Cmnd *);
-};
-
-/* Bitfield meanings for the above registers. */
-
-/* ESP config reg 1, read-write, found on all ESP chips */
-#define ESP_CONFIG1_ID        0x07             /* My BUS ID bits */
-#define ESP_CONFIG1_CHTEST    0x08             /* Enable ESP chip tests */
-#define ESP_CONFIG1_PENABLE   0x10             /* Enable parity checks */
-#define ESP_CONFIG1_PARTEST   0x20             /* Parity test mode enabled? */
-#define ESP_CONFIG1_SRRDISAB  0x40             /* Disable SCSI reset reports */
-#define ESP_CONFIG1_SLCABLE   0x80             /* Enable slow cable mode */
-
-/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236+fsc chips */
-#define ESP_CONFIG2_DMAPARITY 0x01             /* enable DMA Parity (200,236,fsc) */
-#define ESP_CONFIG2_REGPARITY 0x02             /* enable reg Parity (200,236,fsc) */
-#define ESP_CONFIG2_BADPARITY 0x04             /* Bad parity target abort  */
-#define ESP_CONFIG2_SCSI2ENAB 0x08             /* Enable SCSI-2 features (tmode only) */
-#define ESP_CONFIG2_HI        0x10             /* High Impedance DREQ ???  */
-#define ESP_CONFIG2_HMEFENAB  0x10             /* HME features enable */
-#define ESP_CONFIG2_BCM       0x20             /* Enable byte-ctrl (236,fsc)   */
-#define ESP_CONFIG2_FENAB     0x40             /* Enable features (fas100,esp216,fsc)      */
-#define ESP_CONFIG2_SPL       0x40             /* Enable status-phase latch (esp236)   */
-#define ESP_CONFIG2_RFB       0x80             /* Reserve FIFO byte (fsc) */
-#define ESP_CONFIG2_MAGIC     0xe0             /* Invalid bits... */
-
-/* ESP config register 3 read-write, found only esp236+fas236+fas100a+fsc chips */
-#define ESP_CONFIG3_FCLOCK    0x01             /* FAST SCSI clock rate (esp100a/fas366) */
-#define ESP_CONFIG3_TEM       0x01             /* Enable thresh-8 mode (esp/fas236/fsc)  */
-#define ESP_CONFIG3_FAST      0x02             /* Enable FAST SCSI     (esp100a) */
-#define ESP_CONFIG3_ADMA      0x02             /* Enable alternate-dma (esp/fas236/fsc)  */
-#define ESP_CONFIG3_TENB      0x04             /* group2 SCSI2 support (esp100a) */
-#define ESP_CONFIG3_SRB       0x04             /* Save residual byte   (esp/fas236/fsc)  */
-#define ESP_CONFIG3_TMS       0x08             /* Three-byte msg's ok  (esp100a) */
-#define ESP_CONFIG3_FCLK      0x08             /* Fast SCSI clock rate (esp/fas236/fsc)  */
-#define ESP_CONFIG3_IDMSG     0x10             /* ID message checking  (esp100a) */
-#define ESP_CONFIG3_FSCSI     0x10             /* Enable FAST SCSI     (esp/fas236/fsc)  */
-#define ESP_CONFIG3_GTM       0x20             /* group2 SCSI2 support (esp/fas236/fsc)  */
-#define ESP_CONFIG3_TBMS      0x40             /* Three-byte msg's ok  (esp/fas236/fsc)  */
-#define ESP_CONFIG3_IMS       0x80             /* ID msg chk'ng        (esp/fas236/fsc)  */
-
-/* ESP config register 4 read-write, found only on fsc chips */
-#define ESP_CONFIG4_BBTE      0x01             /* Back-to-Back transfer enable */
-#define ESP_CONFIG4_TEST      0x02             /* Transfer counter test mode */
-#define ESP_CONFIG4_EAN       0x04             /* Enable Active Negotiation */
-
-/* ESP command register read-write */
-/* Group 1 commands:  These may be sent at any point in time to the ESP
- *                    chip.  None of them can generate interrupts 'cept
- *                    the "SCSI bus reset" command if you have not disabled
- *                    SCSI reset interrupts in the config1 ESP register.
- */
-#define ESP_CMD_NULL          0x00             /* Null command, ie. a nop */
-#define ESP_CMD_FLUSH         0x01             /* FIFO Flush */
-#define ESP_CMD_RC            0x02             /* Chip reset */
-#define ESP_CMD_RS            0x03             /* SCSI bus reset */
-
-/* Group 2 commands:  ESP must be an initiator and connected to a target
- *                    for these commands to work.
- */
-#define ESP_CMD_TI            0x10             /* Transfer Information */
-#define ESP_CMD_ICCSEQ        0x11             /* Initiator cmd complete sequence */
-#define ESP_CMD_MOK           0x12             /* Message okie-dokie */
-#define ESP_CMD_TPAD          0x18             /* Transfer Pad */
-#define ESP_CMD_SATN          0x1a             /* Set ATN */
-#define ESP_CMD_RATN          0x1b             /* De-assert ATN */
-
-/* Group 3 commands:  ESP must be in the MSGOUT or MSGIN state and be connected
- *                    to a target as the initiator for these commands to work.
- */
-#define ESP_CMD_SMSG          0x20             /* Send message */
-#define ESP_CMD_SSTAT         0x21             /* Send status */
-#define ESP_CMD_SDATA         0x22             /* Send data */
-#define ESP_CMD_DSEQ          0x23             /* Discontinue Sequence */
-#define ESP_CMD_TSEQ          0x24             /* Terminate Sequence */
-#define ESP_CMD_TCCSEQ        0x25             /* Target cmd cmplt sequence */
-#define ESP_CMD_DCNCT         0x27             /* Disconnect */
-#define ESP_CMD_RMSG          0x28             /* Receive Message */
-#define ESP_CMD_RCMD          0x29             /* Receive Command */
-#define ESP_CMD_RDATA         0x2a             /* Receive Data */
-#define ESP_CMD_RCSEQ         0x2b             /* Receive cmd sequence */
-
-/* Group 4 commands:  The ESP must be in the disconnected state and must
- *                    not be connected to any targets as initiator for
- *                    these commands to work.
- */
-#define ESP_CMD_RSEL          0x40             /* Reselect */
-#define ESP_CMD_SEL           0x41             /* Select w/o ATN */
-#define ESP_CMD_SELA          0x42             /* Select w/ATN */
-#define ESP_CMD_SELAS         0x43             /* Select w/ATN & STOP */
-#define ESP_CMD_ESEL          0x44             /* Enable selection */
-#define ESP_CMD_DSEL          0x45             /* Disable selections */
-#define ESP_CMD_SA3           0x46             /* Select w/ATN3 */
-#define ESP_CMD_RSEL3         0x47             /* Reselect3 */
-
-/* This bit enables the ESP's DMA */
-#define ESP_CMD_DMA           0x80             /* Do DMA? */
-
-/* ESP status register read-only */
-#define ESP_STAT_PIO          0x01             /* IO phase bit */
-#define ESP_STAT_PCD          0x02             /* CD phase bit */
-#define ESP_STAT_PMSG         0x04             /* MSG phase bit */
-#define ESP_STAT_PMASK        0x07             /* Mask of phase bits */
-#define ESP_STAT_TDONE        0x08             /* Transfer Completed */
-#define ESP_STAT_TCNT         0x10             /* Transfer Counter Is Zero */
-#define ESP_STAT_PERR         0x20             /* Parity error */
-#define ESP_STAT_SPAM         0x40             /* Real bad error */
-/* This indicates the 'interrupt pending' condition, it is a reserved
- * bit on old revs of the ESP (ESP100, ESP100A, FAS100A).
- */
-#define ESP_STAT_INTR         0x80             /* Interrupt */
-
-/* The status register can be masked with ESP_STAT_PMASK and compared
- * with the following values to determine the current phase the ESP
- * (at least thinks it) is in.  For our purposes we also add our own
- * software 'done' bit for our phase management engine.
- */
-#define ESP_DOP   (0)                                       /* Data Out  */
-#define ESP_DIP   (ESP_STAT_PIO)                            /* Data In   */
-#define ESP_CMDP  (ESP_STAT_PCD)                            /* Command   */
-#define ESP_STATP (ESP_STAT_PCD|ESP_STAT_PIO)               /* Status    */
-#define ESP_MOP   (ESP_STAT_PMSG|ESP_STAT_PCD)              /* Message Out */
-#define ESP_MIP   (ESP_STAT_PMSG|ESP_STAT_PCD|ESP_STAT_PIO) /* Message In */
-
-/* ESP interrupt register read-only */
-#define ESP_INTR_S            0x01             /* Select w/o ATN */
-#define ESP_INTR_SATN         0x02             /* Select w/ATN */
-#define ESP_INTR_RSEL         0x04             /* Reselected */
-#define ESP_INTR_FDONE        0x08             /* Function done */
-#define ESP_INTR_BSERV        0x10             /* Bus service */
-#define ESP_INTR_DC           0x20             /* Disconnect */
-#define ESP_INTR_IC           0x40             /* Illegal command given */
-#define ESP_INTR_SR           0x80             /* SCSI bus reset detected */
-
-/* Interrupt status macros */
-#define ESP_SRESET_IRQ(esp)  ((esp)->intreg & (ESP_INTR_SR))
-#define ESP_ILLCMD_IRQ(esp)  ((esp)->intreg & (ESP_INTR_IC))
-#define ESP_SELECT_WITH_ATN_IRQ(esp)     ((esp)->intreg & (ESP_INTR_SATN))
-#define ESP_SELECT_WITHOUT_ATN_IRQ(esp)  ((esp)->intreg & (ESP_INTR_S))
-#define ESP_SELECTION_IRQ(esp)  ((ESP_SELECT_WITH_ATN_IRQ(esp)) ||         \
-				 (ESP_SELECT_WITHOUT_ATN_IRQ(esp)))
-#define ESP_RESELECTION_IRQ(esp)         ((esp)->intreg & (ESP_INTR_RSEL))
-
-/* ESP sequence step register read-only */
-#define ESP_STEP_VBITS        0x07             /* Valid bits */
-#define ESP_STEP_ASEL         0x00             /* Selection&Arbitrate cmplt */
-#define ESP_STEP_SID          0x01             /* One msg byte sent */
-#define ESP_STEP_NCMD         0x02             /* Was not in command phase */
-#define ESP_STEP_PPC          0x03             /* Early phase chg caused cmnd
-                                                * bytes to be lost
-                                                */
-#define ESP_STEP_FINI4        0x04             /* Command was sent ok */
-
-/* Ho hum, some ESP's set the step register to this as well... */
-#define ESP_STEP_FINI5        0x05
-#define ESP_STEP_FINI6        0x06
-#define ESP_STEP_FINI7        0x07
-#define ESP_STEP_SOM          0x08             /* Synchronous Offset Max */
-
-/* ESP chip-test register read-write */
-#define ESP_TEST_TARG         0x01             /* Target test mode */
-#define ESP_TEST_INI          0x02             /* Initiator test mode */
-#define ESP_TEST_TS           0x04             /* Tristate test mode */
-
-/* ESP unique ID register read-only, found on fas236+fas100a+fsc only */
-#define ESP_UID_F100A         0x00             /* FAS100A  */
-#define ESP_UID_F236          0x02             /* FAS236   */
-#define ESP_UID_FSC           0xa2             /* NCR53CF9x-2  */
-#define ESP_UID_REV           0x07             /* ESP revision */
-#define ESP_UID_FAM           0xf8             /* ESP family   */
-
-/* ESP fifo flags register read-only */
-/* Note that the following implies a 16 byte FIFO on the ESP. */
-#define ESP_FF_FBYTES         0x1f             /* Num bytes in FIFO */
-#define ESP_FF_ONOTZERO       0x20             /* offset ctr not zero (esp100,fsc) */
-#define ESP_FF_SSTEP          0xe0             /* Sequence step */
-
-/* ESP clock conversion factor register write-only */
-#define ESP_CCF_F0            0x00             /* 35.01MHz - 40MHz */
-#define ESP_CCF_NEVER         0x01             /* Set it to this and die */
-#define ESP_CCF_F2            0x02             /* 10MHz */
-#define ESP_CCF_F3            0x03             /* 10.01MHz - 15MHz */
-#define ESP_CCF_F4            0x04             /* 15.01MHz - 20MHz */
-#define ESP_CCF_F5            0x05             /* 20.01MHz - 25MHz */
-#define ESP_CCF_F6            0x06             /* 25.01MHz - 30MHz */
-#define ESP_CCF_F7            0x07             /* 30.01MHz - 35MHz */
-
-#define ESP_BUS_TIMEOUT        275             /* In milli-seconds */
-#define ESP_TIMEO_CONST       8192
-#define FSC_TIMEO_CONST       7668
-#define ESP_NEG_DEFP(mhz, cfact) \
-        ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
-#define FSC_NEG_DEFP(mhz, cfact) \
-        ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (7668 * (cfact)))
-#define ESP_MHZ_TO_CYCLE(mhertz)  ((1000000000) / ((mhertz) / 1000))
-#define ESP_TICK(ccf, cycle)  ((7682 * (ccf) * (cycle) / 1000))
-
-
-/* UGLY, UGLY, UGLY! */
-extern int nesps, esps_in_use, esps_running;
-
-/* For our interrupt engine. */
-#define for_each_esp(esp) \
-        for((esp) = espchain; (esp); (esp) = (esp)->next)
-
-
-/* External functions */
-extern void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs);
-extern struct NCR_ESP *esp_allocate(struct scsi_host_template *, void *, int);
-extern void esp_deallocate(struct NCR_ESP *);
-extern void esp_release(void);
-extern void esp_initialize(struct NCR_ESP *);
-extern irqreturn_t esp_intr(int, void *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *);
-extern int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length,
-			 int inout);
-extern int esp_slave_alloc(struct scsi_device *);
-extern void esp_slave_destroy(struct scsi_device *);
-#endif /* !(NCR53C9X_H) */
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index d7235f4..bfd0e64 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -859,44 +859,31 @@
 			le32_to_cpu(dev->adapter_info.serial[0]), cid);
 }
 
-static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
-		      u8 a_sense_code, u8 incorrect_length,
-		      u8 bit_pointer, u16 field_pointer,
-		      u32 residue)
+static inline void set_sense(struct sense_data *sense_data, u8 sense_key,
+	u8 sense_code, u8 a_sense_code, u8 bit_pointer, u16 field_pointer)
 {
-	sense_buf[0] = 0xF0;	/* Sense data valid, err code 70h (current error) */
+	u8 *sense_buf = (u8 *)sense_data;
+	/* Sense data valid, err code 70h */
+	sense_buf[0] = 0x70; /* No info field */
 	sense_buf[1] = 0;	/* Segment number, always zero */
 
-	if (incorrect_length) {
-		sense_buf[2] = sense_key | 0x20;/* Set ILI bit | sense key */
-		sense_buf[3] = BYTE3(residue);
-		sense_buf[4] = BYTE2(residue);
-		sense_buf[5] = BYTE1(residue);
-		sense_buf[6] = BYTE0(residue);
-	} else
-		sense_buf[2] = sense_key;	/* Sense key */
-
-	if (sense_key == ILLEGAL_REQUEST)
-		sense_buf[7] = 10;	/* Additional sense length */
-	else
-		sense_buf[7] = 6;	/* Additional sense length */
+	sense_buf[2] = sense_key;	/* Sense key */
 
 	sense_buf[12] = sense_code;	/* Additional sense code */
 	sense_buf[13] = a_sense_code;	/* Additional sense code qualifier */
+
 	if (sense_key == ILLEGAL_REQUEST) {
-		sense_buf[15] = 0;
+		sense_buf[7] = 10;	/* Additional sense length */
 
-		if (sense_code == SENCODE_INVALID_PARAM_FIELD)
-			sense_buf[15] = 0x80;/* Std sense key specific field */
+		sense_buf[15] = bit_pointer;
 		/* Illegal parameter is in the parameter block */
-
 		if (sense_code == SENCODE_INVALID_CDB_FIELD)
-			sense_buf[15] = 0xc0;/* Std sense key specific field */
+			sense_buf[15] |= 0xc0;/* Std sense key specific field */
 		/* Illegal parameter is in the CDB block */
-		sense_buf[15] |= bit_pointer;
 		sense_buf[16] = field_pointer >> 8;	/* MSB */
 		sense_buf[17] = field_pointer;		/* LSB */
-	}
+	} else
+		sense_buf[7] = 6;	/* Additional sense length */
 }
 
 static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
@@ -906,11 +893,9 @@
 		dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
 		cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
 			SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-			    HARDWARE_ERROR,
-			    SENCODE_INTERNAL_TARGET_FAILURE,
-			    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-			    0, 0);
+		set_sense(&dev->fsa_dev[cid].sense_data,
+		  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+		  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
 		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
 			     SCSI_SENSE_BUFFERSIZE));
@@ -1520,11 +1505,9 @@
 		  le32_to_cpu(readreply->status));
 #endif
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-				    HARDWARE_ERROR,
-				    SENCODE_INTERNAL_TARGET_FAILURE,
-				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-				    0, 0);
+		set_sense(&dev->fsa_dev[cid].sense_data,
+		  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+		  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
 		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
 			     SCSI_SENSE_BUFFERSIZE));
@@ -1733,11 +1716,9 @@
 		     le32_to_cpu(synchronizereply->status));
 		cmd->result = DID_OK << 16 |
 			COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *)&dev->fsa_dev[cid].sense_data,
-				    HARDWARE_ERROR,
-				    SENCODE_INTERNAL_TARGET_FAILURE,
-				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
-				    0, 0);
+		set_sense(&dev->fsa_dev[cid].sense_data,
+		  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+		  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
 		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
 			     SCSI_SENSE_BUFFERSIZE));
@@ -1945,10 +1926,9 @@
 	{
 		dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0]));
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-			    ILLEGAL_REQUEST,
-			    SENCODE_INVALID_COMMAND,
-			    ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
+		set_sense(&dev->fsa_dev[cid].sense_data,
+		  ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
+		  ASENCODE_INVALID_COMMAND, 0, 0);
 		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
 			     SCSI_SENSE_BUFFERSIZE));
@@ -1995,10 +1975,9 @@
 				scsicmd->result = DID_OK << 16 |
 				  COMMAND_COMPLETE << 8 |
 				  SAM_STAT_CHECK_CONDITION;
-				set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-				  ILLEGAL_REQUEST,
-				  SENCODE_INVALID_CDB_FIELD,
-				  ASENCODE_NO_SENSE, 0, 7, 2, 0);
+				set_sense(&dev->fsa_dev[cid].sense_data,
+				  ILLEGAL_REQUEST, SENCODE_INVALID_CDB_FIELD,
+				  ASENCODE_NO_SENSE, 7, 2);
 				memcpy(scsicmd->sense_buffer,
 				  &dev->fsa_dev[cid].sense_data,
 				  min_t(size_t,
@@ -2254,9 +2233,9 @@
 			 */
 			dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
 			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-			set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
-				ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
-				ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
+			set_sense(&dev->fsa_dev[cid].sense_data,
+			  ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
+			  ASENCODE_INVALID_COMMAND, 0, 0);
 			memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 				min_t(size_t,
 				      sizeof(dev->fsa_dev[cid].sense_data),
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index f8afa35..abef051 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -243,6 +243,7 @@
 	 *	Search the list of AdapterFibContext addresses on the adapter
 	 *	to be sure this is a valid address
 	 */
+	spin_lock_irqsave(&dev->fib_lock, flags);
 	entry = dev->fib_list.next;
 	fibctx = NULL;
 
@@ -251,24 +252,25 @@
 		/*
 		 *	Extract the AdapterFibContext from the Input parameters.
 		 */
-		if (fibctx->unique == f.fibctx) {   /* We found a winner */
+		if (fibctx->unique == f.fibctx) { /* We found a winner */
 			break;
 		}
 		entry = entry->next;
 		fibctx = NULL;
 	}
 	if (!fibctx) {
+		spin_unlock_irqrestore(&dev->fib_lock, flags);
 		dprintk ((KERN_INFO "Fib Context not found\n"));
 		return -EINVAL;
 	}
 
 	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
 		 (fibctx->size != sizeof(struct aac_fib_context))) {
+		spin_unlock_irqrestore(&dev->fib_lock, flags);
 		dprintk ((KERN_INFO "Fib Context corrupt?\n"));
 		return -EINVAL;
 	}
 	status = 0;
-	spin_lock_irqsave(&dev->fib_lock, flags);
 	/*
 	 *	If there are no fibs to send back, then either wait or return
 	 *	-EAGAIN
@@ -414,8 +416,8 @@
  *	@arg: ioctl arguments
  *
  *	This routine returns the driver version.
- *      Under Linux, there have been no version incompatibilities, so this is
- *      simple!
+ *	Under Linux, there have been no version incompatibilities, so this is
+ *	simple!
  */
 
 static int check_revision(struct aac_dev *dev, void __user *arg)
@@ -463,7 +465,7 @@
 	u32 data_dir;
 	void __user *sg_user[32];
 	void *sg_list[32];
-	u32   sg_indx = 0;
+	u32 sg_indx = 0;
 	u32 byte_count = 0;
 	u32 actual_fibsize64, actual_fibsize = 0;
 	int i;
@@ -517,11 +519,11 @@
 	// Fix up srb for endian and force some values
 
 	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);	// Force this
-	srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);
+	srbcmd->channel	 = cpu_to_le32(user_srbcmd->channel);
 	srbcmd->id	 = cpu_to_le32(user_srbcmd->id);
-	srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);
-	srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);
-	srbcmd->flags    = cpu_to_le32(flags);
+	srbcmd->lun	 = cpu_to_le32(user_srbcmd->lun);
+	srbcmd->timeout	 = cpu_to_le32(user_srbcmd->timeout);
+	srbcmd->flags	 = cpu_to_le32(flags);
 	srbcmd->retry_limit = 0; // Obsolete parameter
 	srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
 	memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
@@ -786,9 +788,9 @@
 	pci_info.bus = dev->pdev->bus->number;
 	pci_info.slot = PCI_SLOT(dev->pdev->devfn);
 
-       if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
-	       dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
-	       return -EFAULT;
+	if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
+		dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
+		return -EFAULT;
 	}
 	return 0;
 }
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index fb08861..e80d2a0 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1130,31 +1130,29 @@
 	if (error < 0)
 		goto out_deinit;
 
-	if (!(aac->adapter_info.options & AAC_OPT_NEW_COMM)) {
-		error = pci_set_dma_max_seg_size(pdev, 65536);
-		if (error)
-			goto out_deinit;
-	}
-
 	/*
  	 * Lets override negotiations and drop the maximum SG limit to 34
  	 */
 	if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) &&
-			(aac->scsi_host_ptr->sg_tablesize > 34)) {
- 		aac->scsi_host_ptr->sg_tablesize = 34;
- 		aac->scsi_host_ptr->max_sectors
- 		  = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+			(shost->sg_tablesize > 34)) {
+		shost->sg_tablesize = 34;
+		shost->max_sectors = (shost->sg_tablesize * 8) + 112;
  	}
 
  	if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
-			(aac->scsi_host_ptr->sg_tablesize > 17)) {
- 		aac->scsi_host_ptr->sg_tablesize = 17;
- 		aac->scsi_host_ptr->max_sectors
- 		  = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+			(shost->sg_tablesize > 17)) {
+		shost->sg_tablesize = 17;
+		shost->max_sectors = (shost->sg_tablesize * 8) + 112;
  	}
 
+	error = pci_set_dma_max_seg_size(pdev,
+		(aac->adapter_info.options & AAC_OPT_NEW_COMM) ?
+			(shost->max_sectors << 9) : 65536);
+	if (error)
+		goto out_deinit;
+
 	/*
-	 * Firware printf works only with older firmware.
+	 * Firmware printf works only with older firmware.
 	 */
 	if (aac_drivers[index].quirks & AAC_QUIRK_34SG)
 		aac->printf_enabled = 1;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 374ed02..ccef891 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -12261,7 +12261,7 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void __devinit
+static void __devinit
 AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 {
 	ushort *wbuf;
@@ -12328,7 +12328,7 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void __devinit
+static void __devinit
 AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
 {
 	ushort *wbuf;
@@ -12395,7 +12395,7 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void __devinit
+static void __devinit
 AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
 {
 	ushort *wbuf;
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index a67e29f..5778650 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -48,7 +48,7 @@
 /*The limit of outstanding scsi command that firmware can handle*/
 #define ARCMSR_MAX_OUTSTANDING_CMD						256
 #define ARCMSR_MAX_FREECCB_NUM							320
-#define ARCMSR_DRIVER_VERSION		     "Driver Version 1.20.00.15 2007/08/30"
+#define ARCMSR_DRIVER_VERSION		     "Driver Version 1.20.00.15 2007/12/24"
 #define ARCMSR_SCSI_INITIATOR_ID						255
 #define ARCMSR_MAX_XFER_SECTORS							512
 #define ARCMSR_MAX_XFER_SECTORS_B						4096
@@ -248,6 +248,7 @@
 #define ARCMSR_MESSAGE_START_BGRB		      0x00060008
 #define ARCMSR_MESSAGE_START_DRIVER_MODE	      0x000E0008
 #define ARCMSR_MESSAGE_SET_POST_WINDOW		      0x000F0008
+#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE		    0x00100008
 /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
 #define ARCMSR_MESSAGE_FIRMWARE_OK		      0x80000000
 /* ioctl transfer */
@@ -256,6 +257,7 @@
 #define ARCMSR_DRV2IOP_DATA_READ_OK                   0x00000002
 #define ARCMSR_DRV2IOP_CDB_POSTED                     0x00000004
 #define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED             0x00000008
+#define ARCMSR_DRV2IOP_END_OF_INTERRUPT		0x00000010
 
 /* data tunnel buffer between user space program and its firmware */
 /* user space data to iop 128bytes */
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index f4a202e..4f9ff32 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -315,9 +315,6 @@
 				(0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
 		}
 
-		reg = (struct MessageUnit_B *)(dma_coherent +
-		ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
-
 		dma_addr = dma_coherent_handle;
 		ccb_tmp = (struct CommandControlBlock *)dma_coherent;
 		for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
@@ -371,8 +368,8 @@
 
 out:
 	dma_free_coherent(&acb->pdev->dev,
-		ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20,
-		acb->dma_coherent, acb->dma_coherent_handle);
+		(ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
+		sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
 	return -ENOMEM;
 }
 
@@ -509,6 +506,7 @@
 				& ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
 				writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN
 					, reg->iop2drv_doorbell_reg);
+				writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
 				return 0x00;
 			}
 			msleep(10);
@@ -748,6 +746,7 @@
 				, ccb->startdone
 				, atomic_read(&acb->ccboutstandingcount));
 		}
+	else
 	arcmsr_report_ccb_state(acb, ccb, flag_ccb);
 }
 
@@ -886,7 +885,7 @@
 	}
 }
 
-static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
+static int arcmsr_build_ccb(struct AdapterControlBlock *acb,
 	struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd)
 {
 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
@@ -906,6 +905,8 @@
 	memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
 
 	nseg = scsi_dma_map(pcmd);
+	if (nseg > ARCMSR_MAX_SG_ENTRIES)
+		return FAILED;
 	BUG_ON(nseg < 0);
 
 	if (nseg) {
@@ -946,6 +947,7 @@
 		arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
 		ccb->ccb_flags |= CCB_FLAG_WRITE;
 	}
+	return SUCCESS;
 }
 
 static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb)
@@ -1036,18 +1038,22 @@
 	switch (acb->adapter_type) {
 	case ACB_ADAPTER_TYPE_A: {
 		iounmap(acb->pmuA);
+		dma_free_coherent(&acb->pdev->dev,
+		ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
+		acb->dma_coherent,
+		acb->dma_coherent_handle);
 		break;
 	}
 	case ACB_ADAPTER_TYPE_B: {
 		struct MessageUnit_B *reg = acb->pmuB;
 		iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
 		iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
+		dma_free_coherent(&acb->pdev->dev,
+		(ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
+		sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
 	}
 	}
-	dma_free_coherent(&acb->pdev->dev,
-		ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
-		acb->dma_coherent,
-		acb->dma_coherent_handle);
+
 }
 
 void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
@@ -1273,7 +1279,9 @@
 		return 1;
 
 	writel(~outbound_doorbell, reg->iop2drv_doorbell_reg);
-
+	/*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/
+	readl(reg->iop2drv_doorbell_reg);
+	writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
 	if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) 	{
 		arcmsr_iop2drv_data_wrote_handle(acb);
 	}
@@ -1380,12 +1388,13 @@
 
 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
 		unsigned long *ver_addr;
-		dma_addr_t buf_handle;
 		uint8_t *pQbuffer, *ptmpQbuffer;
 		int32_t allxfer_len = 0;
+		void *tmp;
 
-		ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
-		if (!ver_addr) {
+		tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA);
+		ver_addr = (unsigned long *)tmp;
+		if (!tmp) {
 			retvalue = ARCMSR_MESSAGE_FAIL;
 			goto message_out;
 		}
@@ -1421,18 +1430,19 @@
 		memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len);
 		pcmdmessagefld->cmdmessage.Length = allxfer_len;
 		pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
-		pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
+		kfree(tmp);
 		}
 		break;
 
 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
 		unsigned long *ver_addr;
-		dma_addr_t buf_handle;
 		int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
 		uint8_t *pQbuffer, *ptmpuserbuffer;
+		void *tmp;
 
-		ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
-		if (!ver_addr) {
+		tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA);
+		ver_addr = (unsigned long *)tmp;
+		if (!tmp) {
 			retvalue = ARCMSR_MESSAGE_FAIL;
 			goto message_out;
 		}
@@ -1482,7 +1492,7 @@
 				retvalue = ARCMSR_MESSAGE_FAIL;
 			}
 			}
-			pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
+			kfree(tmp);
 		}
 		break;
 
@@ -1682,8 +1692,11 @@
 	ccb = arcmsr_get_freeccb(acb);
 	if (!ccb)
 		return SCSI_MLQUEUE_HOST_BUSY;
-
-	arcmsr_build_ccb(acb, ccb, cmd);
+	if ( arcmsr_build_ccb( acb, ccb, cmd ) == FAILED ) {
+		cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
+		cmd->scsi_done(cmd);
+		return 0;
+	}
 	arcmsr_post_ccb(acb, ccb);
 	return 0;
 }
@@ -1844,7 +1857,7 @@
 	}
 }
 
-static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
+static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb,
 					struct CommandControlBlock *poll_ccb)
 {
 		struct MessageUnit_B *reg = acb->pmuB;
@@ -1878,7 +1891,7 @@
       (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/
 			poll_ccb_done = (ccb == poll_ccb) ? 1:0;
 			if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
-				if (ccb->startdone == ARCMSR_CCB_ABORTED) {
+				if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) {
 					printk(KERN_NOTICE "arcmsr%d: \
 		scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n"
 						,acb->host->host_no
@@ -1901,7 +1914,7 @@
 		}	/*drain reply FIFO*/
 }
 
-static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \
+static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
 					struct CommandControlBlock *poll_ccb)
 {
 	switch (acb->adapter_type) {
@@ -2026,6 +2039,7 @@
 		do {
 			firmware_state = readl(reg->iop2drv_doorbell_reg);
 		} while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
+		writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
 		}
 		break;
 	}
@@ -2090,19 +2104,39 @@
 	}
 }
 
+static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
+{
+	switch (acb->adapter_type) {
+	case ACB_ADAPTER_TYPE_A:
+		return;
+	case ACB_ADAPTER_TYPE_B:
+		{
+			struct MessageUnit_B *reg = acb->pmuB;
+			writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell_reg);
+			if(arcmsr_hbb_wait_msgint_ready(acb)) {
+				printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT");
+				return;
+			}
+		}
+		break;
+	}
+	return;
+}
+
 static void arcmsr_iop_init(struct AdapterControlBlock *acb)
 {
 	uint32_t intmask_org;
 
-	arcmsr_wait_firmware_ready(acb);
-	arcmsr_iop_confirm(acb);
        /* disable all outbound interrupt */
        intmask_org = arcmsr_disable_outbound_ints(acb);
+	arcmsr_wait_firmware_ready(acb);
+	arcmsr_iop_confirm(acb);
 	arcmsr_get_firmware_spec(acb);
 	/*start background rebuild*/
 	arcmsr_start_adapter_bgrb(acb);
 	/* empty doorbell Qbuffer if door bell ringed */
 	arcmsr_clear_doorbell_queue_buffer(acb);
+	arcmsr_enable_eoi_mode(acb);
 	/* enable outbound Post Queue,outbound doorbell Interrupt */
 	arcmsr_enable_outbound_ints(acb, intmask_org);
 	acb->acb_flags |= ACB_F_IOP_INITED;
@@ -2275,6 +2309,7 @@
 	arcmsr_start_adapter_bgrb(acb);
 	/* empty doorbell Qbuffer if door bell ringed */
 	arcmsr_clear_doorbell_queue_buffer(acb);
+	arcmsr_enable_eoi_mode(acb);
 	/* enable outbound Post Queue,outbound doorbell Interrupt */
 	arcmsr_enable_outbound_ints(acb, intmask_org);
 	acb->acb_flags |= ACB_F_IOP_INITED;
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index eceacf6..3bedf24 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -1790,7 +1790,7 @@
 	return 0;
     }
 
-    residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
+    residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred;
 
     sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
     sbic_arm_writenext(host->scsi.io_port, residual >> 16);
@@ -2270,7 +2270,7 @@
 	case 0x4b:			/* -> PHASE_STATUSIN				*/
 	case 0x8b:			/* -> PHASE_STATUSIN				*/
 	    /* DATA IN -> STATUS */
-	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
 					  acornscsi_sbic_xfcount(host);
 	    acornscsi_dma_stop(host);
 	    acornscsi_readstatusbyte(host);
@@ -2281,7 +2281,7 @@
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
 	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* DATA IN -> MESSAGE OUT */
-	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
 					  acornscsi_sbic_xfcount(host);
 	    acornscsi_dma_stop(host);
 	    acornscsi_sendmessage(host);
@@ -2291,7 +2291,7 @@
 	case 0x4f:			/* message in					*/
 	case 0x8f:			/* message in					*/
 	    /* DATA IN -> MESSAGE IN */
-	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
 					  acornscsi_sbic_xfcount(host);
 	    acornscsi_dma_stop(host);
 	    acornscsi_message(host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
@@ -2319,7 +2319,7 @@
 	case 0x4b:			/* -> PHASE_STATUSIN				*/
 	case 0x8b:			/* -> PHASE_STATUSIN				*/
 	    /* DATA OUT -> STATUS */
-	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
 					  acornscsi_sbic_xfcount(host);
 	    acornscsi_dma_stop(host);
 	    acornscsi_dma_adjust(host);
@@ -2331,7 +2331,7 @@
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
 	case 0x8e:			/* -> PHASE_MSGOUT				*/
 	    /* DATA OUT -> MESSAGE OUT */
-	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
 					  acornscsi_sbic_xfcount(host);
 	    acornscsi_dma_stop(host);
 	    acornscsi_dma_adjust(host);
@@ -2342,7 +2342,7 @@
 	case 0x4f:			/* message in					*/
 	case 0x8f:			/* message in					*/
 	    /* DATA OUT -> MESSAGE IN */
-	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
 					  acornscsi_sbic_xfcount(host);
 	    acornscsi_dma_stop(host);
 	    acornscsi_dma_adjust(host);
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index bb6550e..138a521 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -18,17 +18,32 @@
  * The scatter-gather list handling.  This contains all
  * the yucky stuff that needs to be fixed properly.
  */
+
+/*
+ * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max
+ * entries of uninitialized memory. SCp is from scsi-ml and has a valid
+ * (possibly chained) sg-list
+ */
 static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max)
 {
 	int bufs = SCp->buffers_residual;
 
+	/* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg().
+	 * and to remove this BUG_ON. Use min() in-its-place
+	 */
 	BUG_ON(bufs + 1 > max);
 
 	sg_set_buf(sg, SCp->ptr, SCp->this_residual);
 
-	if (bufs)
-		memcpy(sg + 1, SCp->buffer + 1,
-		       sizeof(struct scatterlist) * bufs);
+	if (bufs) {
+		struct scatterlist *src_sg;
+		unsigned i;
+
+		for_each_sg(sg_next(SCp->buffer), src_sg, bufs, i)
+			*(++sg) = *src_sg;
+		sg_mark_end(sg);
+	}
+
 	return bufs + 1;
 }
 
@@ -36,7 +51,7 @@
 {
 	int ret = SCp->buffers_residual;
 	if (ret) {
-		SCp->buffer++;
+		SCp->buffer = sg_next(SCp->buffer);
 		SCp->buffers_residual--;
 		SCp->ptr = sg_virt(SCp->buffer);
 		SCp->this_residual = SCp->buffer->length;
@@ -68,46 +83,46 @@
 {
 	memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer));
 
-	if (SCpnt->use_sg) {
+	if (scsi_bufflen(SCpnt)) {
 		unsigned long len = 0;
-		int buf;
 
-		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
-		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
+		SCpnt->SCp.buffer = scsi_sglist(SCpnt);
+		SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1;
 		SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer);
 		SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
-		SCpnt->SCp.phase = SCpnt->request_bufflen;
+		SCpnt->SCp.phase = scsi_bufflen(SCpnt);
 
 #ifdef BELT_AND_BRACES
-		/*
-		 * Calculate correct buffer length.  Some commands
-		 * come in with the wrong request_bufflen.
-		 */
-		for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)
-			len += SCpnt->SCp.buffer[buf].length;
+		{	/*
+			 * Calculate correct buffer length.  Some commands
+			 * come in with the wrong scsi_bufflen.
+			 */
+			struct scatterlist *sg;
+			unsigned i, sg_count = scsi_sg_count(SCpnt);
 
-		if (SCpnt->request_bufflen != len)
-			printk(KERN_WARNING "scsi%d.%c: bad request buffer "
-			       "length %d, should be %ld\n", SCpnt->device->host->host_no,
-			       '0' + SCpnt->device->id, SCpnt->request_bufflen, len);
-		SCpnt->request_bufflen = len;
+			scsi_for_each_sg(SCpnt, sg, sg_count, i)
+				len += sg->length;
+
+			if (scsi_bufflen(SCpnt) != len) {
+				printk(KERN_WARNING
+				       "scsi%d.%c: bad request buffer "
+				       "length %d, should be %ld\n",
+					SCpnt->device->host->host_no,
+					'0' + SCpnt->device->id,
+					scsi_bufflen(SCpnt), len);
+				/*
+				 * FIXME: Totaly naive fixup. We should abort
+				 * with error
+				 */
+				SCpnt->SCp.phase =
+					min_t(unsigned long, len,
+					      scsi_bufflen(SCpnt));
+			}
+		}
 #endif
 	} else {
-		SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
-		SCpnt->SCp.this_residual = SCpnt->request_bufflen;
-		SCpnt->SCp.phase = SCpnt->request_bufflen;
-	}
-
-	/*
-	 * If the upper SCSI layers pass a buffer, but zero length,
-	 * we aren't interested in the buffer pointer.
-	 */
-	if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) {
-#if 0 //def BELT_AND_BRACES
-		printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for "
-		       "command ", SCpnt->host->host_no, '0' + SCpnt->target);
-		__scsi_print_command(SCpnt->cmnd);
-#endif
 		SCpnt->SCp.ptr = NULL;
+		SCpnt->SCp.this_residual = 0;
+		SCpnt->SCp.phase = 0;
 	}
 }
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
deleted file mode 100644
index 23f7c24..0000000
--- a/drivers/scsi/blz1230.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/* blz1230.c: Driver for Blizzard 1230 SCSI IV Controller.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * This driver is based on the CyberStorm driver, hence the occasional
- * reference to CyberStorm.
- */
-
-/* TODO:
- *
- * 1) Figure out how to make a cleaner merge with the sparc driver with regard
- *    to the caches and the Sparc MMU mapping.
- * 2) Make as few routines required outside the generic driver. A lot of the
- *    routines in this file used to be inline!
- */
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#include <asm/pgtable.h>
-
-#define MKIV 1
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define BLZ1230_ESP_ADDR 0x8000
-#define BLZ1230_DMA_ADDR 0x10000
-#define BLZ1230II_ESP_ADDR 0x10000
-#define BLZ1230II_DMA_ADDR 0x10021
-
-
-/* The Blizzard 1230 DMA interface
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Only two things can be programmed in the Blizzard DMA:
- *  1) The data direction is controlled by the status of bit 31 (1 = write)
- *  2) The source/dest address (word aligned, shifted one right) in bits 30-0
- *
- * Program DMA by first latching the highest byte of the address/direction
- * (i.e. bits 31-24 of the long word constructed as described in steps 1+2
- * above). Then write each byte of the address/direction (starting with the
- * top byte, working down) to the DMA address register.
- *
- * Figure out interrupt status by reading the ESP status byte.
- */
-struct blz1230_dma_registers {
-	volatile unsigned char dma_addr; 	/* DMA address      [0x0000] */
-	unsigned char dmapad2[0x7fff];
-	volatile unsigned char dma_latch; 	/* DMA latch        [0x8000] */
-};
-
-struct blz1230II_dma_registers {
-	volatile unsigned char dma_addr; 	/* DMA address      [0x0000] */
-	unsigned char dmapad2[0xf];
-	volatile unsigned char dma_latch; 	/* DMA latch        [0x0010] */
-};
-
-#define BLZ1230_DMA_WRITE 0x80000000
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are transferred to the ESP chip
-				 * via PIO.
-				 */
-
-/***************************************************************** Detection */
-int __init blz1230_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	struct zorro_dev *z = NULL;
-	unsigned long address;
-	struct ESP_regs *eregs;
-	unsigned long board;
-
-#if MKIV
-#define REAL_BLZ1230_ID		ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260
-#define REAL_BLZ1230_ESP_ADDR	BLZ1230_ESP_ADDR
-#define REAL_BLZ1230_DMA_ADDR	BLZ1230_DMA_ADDR
-#else
-#define REAL_BLZ1230_ID		ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060
-#define REAL_BLZ1230_ESP_ADDR	BLZ1230II_ESP_ADDR
-#define REAL_BLZ1230_DMA_ADDR	BLZ1230II_DMA_ADDR
-#endif
-
-	if ((z = zorro_find_device(REAL_BLZ1230_ID, z))) {
-	    board = z->resource.start;
-	    if (request_mem_region(board+REAL_BLZ1230_ESP_ADDR,
-				   sizeof(struct ESP_regs), "NCR53C9x")) {
-		/* Do some magic to figure out if the blizzard is
-		 * equipped with a SCSI controller
-		 */
-		address = ZTWO_VADDR(board);
-		eregs = (struct ESP_regs *)(address + REAL_BLZ1230_ESP_ADDR);
-		esp = esp_allocate(tpnt, (void *)board + REAL_BLZ1230_ESP_ADDR,
-				   0);
-
-		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
-		udelay(5);
-		if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7))
-			goto err_out;
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = 0;
-		esp->dma_invalidate = 0;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = 0;
-		esp->dma_led_on = 0;
-		esp->dma_led_off = 0;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-
-		/* SCSI chip speed */
-		esp->cfreq = 40000000;
-
-		/* The DMA registers on the Blizzard are mapped
-		 * relative to the device (i.e. in the same Zorro
-		 * I/O block).
-		 */
-		esp->dregs = (void *)(address + REAL_BLZ1230_DMA_ADDR);
-	
-		/* ESP register base */
-		esp->eregs = eregs;
-
-		/* Set the command buffer */
-		esp->esp_command = cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
-
-		esp->irq = IRQ_AMIGA_PORTS;
-		esp->slot = board+REAL_BLZ1230_ESP_ADDR;
-		if (request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
-				 "Blizzard 1230 SCSI IV", esp->ehost))
-			goto err_out;
-
-		/* Figure out our scsi ID on the bus */
-		esp->scsi_id = 7;
-		
-		/* We don't have a differential SCSI-bus. */
-		esp->diff = 0;
-
-		esp_initialize(esp);
-
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-		return esps_in_use;
-	    }
-	}
-	return 0;
- 
- err_out:
-	scsi_unregister(esp->ehost);
-	esp_deallocate(esp);
-	release_mem_region(board+REAL_BLZ1230_ESP_ADDR,
-			   sizeof(struct ESP_regs));
-	return 0;
-}
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Since the Blizzard DMA is fully dedicated to the ESP chip,
-	 * the number of bytes sent (to the ESP chip) equals the number
-	 * of bytes in the FIFO - there is no buffering in the DMA controller.
-	 * XXXX Do I read this right? It is from host to ESP, right?
-	 */
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	/* I don't think there's any limit on the Blizzard DMA. So we use what
-	 * the ESP chip can handle (24 bit).
-	 */
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > 0x1000000)
-		sz = 0x1000000;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
-		amiga_custom.intreqr, amiga_custom.intenar));
-}
-
-void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
-{
-#if MKIV
-	struct blz1230_dma_registers *dregs = 
-		(struct blz1230_dma_registers *) (esp->dregs);
-#else
-	struct blz1230II_dma_registers *dregs = 
-		(struct blz1230II_dma_registers *) (esp->dregs);
-#endif
-
-	cache_clear(addr, length);
-
-	addr >>= 1;
-	addr &= ~(BLZ1230_DMA_WRITE);
-
-	/* First set latch */
-	dregs->dma_latch = (addr >> 24) & 0xff;
-
-	/* Then pump the address to the DMA address register */
-#if MKIV
-	dregs->dma_addr = (addr >> 24) & 0xff;
-#endif
-	dregs->dma_addr = (addr >> 16) & 0xff;
-	dregs->dma_addr = (addr >>  8) & 0xff;
-	dregs->dma_addr = (addr      ) & 0xff;
-}
-
-void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
-{
-#if MKIV
-	struct blz1230_dma_registers *dregs = 
-		(struct blz1230_dma_registers *) (esp->dregs);
-#else
-	struct blz1230II_dma_registers *dregs = 
-		(struct blz1230II_dma_registers *) (esp->dregs);
-#endif
-
-	cache_push(addr, length);
-
-	addr >>= 1;
-	addr |= BLZ1230_DMA_WRITE;
-
-	/* First set latch */
-	dregs->dma_latch = (addr >> 24) & 0xff;
-
-	/* Then pump the address to the DMA address register */
-#if MKIV
-	dregs->dma_addr = (addr >> 24) & 0xff;
-#endif
-	dregs->dma_addr = (addr >> 16) & 0xff;
-	dregs->dma_addr = (addr >>  8) & 0xff;
-	dregs->dma_addr = (addr      ) & 0xff;
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(esp->irq);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return ((amiga_custom.intenar) & IF_PORTS);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if(write){
-		dma_init_read(esp, addr, count);
-	} else {
-		dma_init_write(esp, addr, count);
-	}
-}
-
-#define HOSTS_C
-
-int blz1230_esp_release(struct Scsi_Host *instance)
-{
-#ifdef MODULE
-	unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
-	esp_deallocate((struct NCR_ESP *)instance->hostdata);
-	esp_release();
-	release_mem_region(address, sizeof(struct ESP_regs));
-	free_irq(IRQ_AMIGA_PORTS, esp_intr);
-#endif
-	return 1;
-}
-
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp-blz1230",
-	.proc_info		= esp_proc_info,
-	.name			= "Blizzard1230 SCSI IV",
-	.detect			= blz1230_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= blz1230_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
deleted file mode 100644
index b6203ec..0000000
--- a/drivers/scsi/blz2060.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* blz2060.c: Driver for Blizzard 2060 SCSI Controller.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * This driver is based on the CyberStorm driver, hence the occasional
- * reference to CyberStorm.
- */
-
-/* TODO:
- *
- * 1) Figure out how to make a cleaner merge with the sparc driver with regard
- *    to the caches and the Sparc MMU mapping.
- * 2) Make as few routines required outside the generic driver. A lot of the
- *    routines in this file used to be inline!
- */
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#include <asm/pgtable.h>
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define BLZ2060_ESP_ADDR 0x1ff00
-#define BLZ2060_DMA_ADDR 0x1ffe0
-
-
-/* The Blizzard 2060 DMA interface
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Only two things can be programmed in the Blizzard DMA:
- *  1) The data direction is controlled by the status of bit 31 (1 = write)
- *  2) The source/dest address (word aligned, shifted one right) in bits 30-0
- *
- * Figure out interrupt status by reading the ESP status byte.
- */
-struct blz2060_dma_registers {
-	volatile unsigned char dma_led_ctrl;	/* DMA led control   [0x000] */
-	unsigned char dmapad1[0x0f];
-	volatile unsigned char dma_addr0; 	/* DMA address (MSB) [0x010] */
-	unsigned char dmapad2[0x03];
-	volatile unsigned char dma_addr1; 	/* DMA address       [0x014] */
-	unsigned char dmapad3[0x03];
-	volatile unsigned char dma_addr2; 	/* DMA address       [0x018] */
-	unsigned char dmapad4[0x03];
-	volatile unsigned char dma_addr3; 	/* DMA address (LSB) [0x01c] */
-};
-
-#define BLZ2060_DMA_WRITE 0x80000000
-
-/* DMA control bits */
-#define BLZ2060_DMA_LED    0x02		/* HD led control 1 = off */
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static void dma_led_off(struct NCR_ESP *esp);
-static void dma_led_on(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are transferred to the ESP chip
-				 * via PIO.
-				 */
-
-/***************************************************************** Detection */
-int __init blz2060_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	struct zorro_dev *z = NULL;
-	unsigned long address;
-
-	if ((z = zorro_find_device(ZORRO_PROD_PHASE5_BLIZZARD_2060, z))) {
-	    unsigned long board = z->resource.start;
-	    if (request_mem_region(board+BLZ2060_ESP_ADDR,
-				   sizeof(struct ESP_regs), "NCR53C9x")) {
-		esp = esp_allocate(tpnt, (void *)board + BLZ2060_ESP_ADDR, 0);
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = 0;
-		esp->dma_invalidate = 0;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = 0;
-		esp->dma_led_on = &dma_led_on;
-		esp->dma_led_off = &dma_led_off;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-
-		/* SCSI chip speed */
-		esp->cfreq = 40000000;
-
-		/* The DMA registers on the Blizzard are mapped
-		 * relative to the device (i.e. in the same Zorro
-		 * I/O block).
-		 */
-		address = (unsigned long)ZTWO_VADDR(board);
-		esp->dregs = (void *)(address + BLZ2060_DMA_ADDR);
-
-		/* ESP register base */
-		esp->eregs = (struct ESP_regs *)(address + BLZ2060_ESP_ADDR);
-		
-		/* Set the command buffer */
-		esp->esp_command = cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
-
-		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
-			    "Blizzard 2060 SCSI", esp->ehost);
-
-		/* Figure out our scsi ID on the bus */
-		esp->scsi_id = 7;
-		
-		/* We don't have a differential SCSI-bus. */
-		esp->diff = 0;
-
-		esp_initialize(esp);
-
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-		return esps_in_use;
-	    }
-	}
-	return 0;
-}
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Since the Blizzard DMA is fully dedicated to the ESP chip,
-	 * the number of bytes sent (to the ESP chip) equals the number
-	 * of bytes in the FIFO - there is no buffering in the DMA controller.
-	 * XXXX Do I read this right? It is from host to ESP, right?
-	 */
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	/* I don't think there's any limit on the Blizzard DMA. So we use what
-	 * the ESP chip can handle (24 bit).
-	 */
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > 0x1000000)
-		sz = 0x1000000;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
-		amiga_custom.intreqr, amiga_custom.intenar));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct blz2060_dma_registers *dregs = 
-		(struct blz2060_dma_registers *) (esp->dregs);
-
-	cache_clear(addr, length);
-
-	addr >>= 1;
-	addr &= ~(BLZ2060_DMA_WRITE);
-	dregs->dma_addr3 = (addr      ) & 0xff;
-	dregs->dma_addr2 = (addr >>  8) & 0xff;
-	dregs->dma_addr1 = (addr >> 16) & 0xff;
-	dregs->dma_addr0 = (addr >> 24) & 0xff;
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct blz2060_dma_registers *dregs = 
-		(struct blz2060_dma_registers *) (esp->dregs);
-
-	cache_push(addr, length);
-
-	addr >>= 1;
-	addr |= BLZ2060_DMA_WRITE;
-	dregs->dma_addr3 = (addr      ) & 0xff;
-	dregs->dma_addr2 = (addr >>  8) & 0xff;
-	dregs->dma_addr1 = (addr >> 16) & 0xff;
-	dregs->dma_addr0 = (addr >> 24) & 0xff;
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(esp->irq);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
-}
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-	((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl =
-		BLZ2060_DMA_LED;
-}
-
-static void dma_led_on(struct NCR_ESP *esp)
-{
-	((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl = 0;
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return ((amiga_custom.intenar) & IF_PORTS);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if(write){
-		dma_init_read(esp, addr, count);
-	} else {
-		dma_init_write(esp, addr, count);
-	}
-}
-
-#define HOSTS_C
-
-int blz2060_esp_release(struct Scsi_Host *instance)
-{
-#ifdef MODULE
-	unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
-
-	esp_deallocate((struct NCR_ESP *)instance->hostdata);
-	esp_release();
-	release_mem_region(address, sizeof(struct ESP_regs));
-	free_irq(IRQ_AMIGA_PORTS, esp_intr);
-#endif
-	return 1;
-}
-
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp-blz2060",
-	.proc_info		= esp_proc_info,
-	.name			= "Blizzard2060 SCSI",
-	.detect			= blz2060_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= blz2060_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
deleted file mode 100644
index c6b98a4..0000000
--- a/drivers/scsi/cyberstorm.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* cyberstorm.c: Driver for CyberStorm SCSI Controller.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * The CyberStorm SCSI driver is based on David S. Miller's ESP driver
- * for the Sparc computers. 
- * 
- * This work was made possible by Phase5 who willingly (and most generously)
- * supported me with hardware and all the information I needed.
- */
-
-/* TODO:
- *
- * 1) Figure out how to make a cleaner merge with the sparc driver with regard
- *    to the caches and the Sparc MMU mapping.
- * 2) Make as few routines required outside the generic driver. A lot of the
- *    routines in this file used to be inline!
- */
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#include <asm/pgtable.h>
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define CYBER_ESP_ADDR 0xf400
-#define CYBER_DMA_ADDR 0xf800
-
-
-/* The CyberStorm DMA interface */
-struct cyber_dma_registers {
-	volatile unsigned char dma_addr0;	/* DMA address (MSB) [0x000] */
-	unsigned char dmapad1[1];
-	volatile unsigned char dma_addr1;	/* DMA address       [0x002] */
-	unsigned char dmapad2[1];
-	volatile unsigned char dma_addr2;	/* DMA address       [0x004] */
-	unsigned char dmapad3[1];
-	volatile unsigned char dma_addr3;	/* DMA address (LSB) [0x006] */
-	unsigned char dmapad4[0x3fb];
-	volatile unsigned char cond_reg;        /* DMA cond    (ro)  [0x402] */
-#define ctrl_reg  cond_reg			/* DMA control (wo)  [0x402] */
-};
-
-/* DMA control bits */
-#define CYBER_DMA_LED    0x80	/* HD led control 1 = on */
-#define CYBER_DMA_WRITE  0x40	/* DMA direction. 1 = write */
-#define CYBER_DMA_Z3     0x20	/* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */
-
-/* DMA status bits */
-#define CYBER_DMA_HNDL_INTR 0x80	/* DMA IRQ pending? */
-
-/* The bits below appears to be Phase5 Debug bits only; they were not
- * described by Phase5 so using them may seem a bit stupid...
- */
-#define CYBER_HOST_ID 0x02	/* If set, host ID should be 7, otherwise
-				 * it should be 6.
-				 */
-#define CYBER_SLOW_CABLE 0x08	/* If *not* set, assume SLOW_CABLE */
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static void dma_led_off(struct NCR_ESP *esp);
-static void dma_led_on(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-
-static unsigned char ctrl_data = 0;	/* Keep backup of the stuff written
-				 * to ctrl_reg. Always write a copy
-				 * to this register when writing to
-				 * the hardware register!
-				 */
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are transferred to the ESP chip
-				 * via PIO.
-				 */
-
-/***************************************************************** Detection */
-int __init cyber_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	struct zorro_dev *z = NULL;
-	unsigned long address;
-
-	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-	    unsigned long board = z->resource.start;
-	    if ((z->id == ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM ||
-		 z->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060) &&
-		request_mem_region(board+CYBER_ESP_ADDR,
-		    		   sizeof(struct ESP_regs), "NCR53C9x")) {
-		/* Figure out if this is a CyberStorm or really a 
-		 * Fastlane/Blizzard Mk II by looking at the board size.
-		 * CyberStorm maps 64kB
-		 * (ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM does anyway)
-		 */
-		if(z->resource.end-board != 0xffff) {
-			release_mem_region(board+CYBER_ESP_ADDR,
-					   sizeof(struct ESP_regs));
-			return 0;
-		}
-		esp = esp_allocate(tpnt, (void *)board + CYBER_ESP_ADDR, 0);
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = 0;
-		esp->dma_invalidate = 0;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = 0;
-		esp->dma_led_on = &dma_led_on;
-		esp->dma_led_off = &dma_led_off;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-
-		/* SCSI chip speed */
-		esp->cfreq = 40000000;
-
-		/* The DMA registers on the CyberStorm are mapped
-		 * relative to the device (i.e. in the same Zorro
-		 * I/O block).
-		 */
-		address = (unsigned long)ZTWO_VADDR(board);
-		esp->dregs = (void *)(address + CYBER_DMA_ADDR);
-
-		/* ESP register base */
-		esp->eregs = (struct ESP_regs *)(address + CYBER_ESP_ADDR);
-		
-		/* Set the command buffer */
-		esp->esp_command = cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
-
-		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
-			    "CyberStorm SCSI", esp->ehost);
-		/* Figure out our scsi ID on the bus */
-		/* The DMA cond flag contains a hardcoded jumper bit
-		 * which can be used to select host number 6 or 7.
-		 * However, even though it may change, we use a hardcoded
-		 * value of 7.
-		 */
-		esp->scsi_id = 7;
-		
-		/* We don't have a differential SCSI-bus. */
-		esp->diff = 0;
-
-		esp_initialize(esp);
-
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-		return esps_in_use;
-	    }
-	}
-	return 0;
-}
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
-	 * the number of bytes sent (to the ESP chip) equals the number
-	 * of bytes in the FIFO - there is no buffering in the DMA controller.
-	 * XXXX Do I read this right? It is from host to ESP, right?
-	 */
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	/* I don't think there's any limit on the CyberDMA. So we use what
-	 * the ESP chip can handle (24 bit).
-	 */
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > 0x1000000)
-		sz = 0x1000000;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
-		esp->esp_id, ((struct cyber_dma_registers *)
-			      (esp->dregs))->cond_reg));
-	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
-		amiga_custom.intreqr, amiga_custom.intenar));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct cyber_dma_registers *dregs = 
-		(struct cyber_dma_registers *) esp->dregs;
-
-	cache_clear(addr, length);
-
-	addr &= ~(1);
-	dregs->dma_addr0 = (addr >> 24) & 0xff;
-	dregs->dma_addr1 = (addr >> 16) & 0xff;
-	dregs->dma_addr2 = (addr >>  8) & 0xff;
-	dregs->dma_addr3 = (addr      ) & 0xff;
-	ctrl_data &= ~(CYBER_DMA_WRITE);
-
-	/* Check if physical address is outside Z2 space and of
-	 * block length/block aligned in memory. If this is the
-	 * case, enable 32 bit transfer. In all other cases, fall back
-	 * to 16 bit transfer.
-	 * Obviously 32 bit transfer should be enabled if the DMA address
-	 * and length are 32 bit aligned. However, this leads to some
-	 * strange behavior. Even 64 bit aligned addr/length fails.
-	 * Until I've found a reason for this, 32 bit transfer is only
-	 * used for full-block transfers (1kB).
-	 *							-jskov
-	 */
-#if 0
-	if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) &&
-						(addr < 0xff0000)))
-		ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
-	else
-		ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */
-#else
-	ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
-#endif
-	dregs->ctrl_reg = ctrl_data;
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct cyber_dma_registers *dregs = 
-		(struct cyber_dma_registers *) esp->dregs;
-
-	cache_push(addr, length);
-
-	addr |= 1;
-	dregs->dma_addr0 = (addr >> 24) & 0xff;
-	dregs->dma_addr1 = (addr >> 16) & 0xff;
-	dregs->dma_addr2 = (addr >>  8) & 0xff;
-	dregs->dma_addr3 = (addr      ) & 0xff;
-	ctrl_data |= CYBER_DMA_WRITE;
-
-	/* See comment above */
-#if 0
-	if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) &&
-						(addr < 0xff0000)))
-		ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
-	else
-		ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */
-#else
-	ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
-#endif
-	dregs->ctrl_reg = ctrl_data;
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(esp->irq);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	/* It's important to check the DMA IRQ bit in the correct way! */
-	return ((esp_read(esp->eregs->esp_status) & ESP_STAT_INTR) &&
-		((((struct cyber_dma_registers *)(esp->dregs))->cond_reg) &
-		 CYBER_DMA_HNDL_INTR));
-}
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-	ctrl_data &= ~CYBER_DMA_LED;
-	((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
-}
-
-static void dma_led_on(struct NCR_ESP *esp)
-{
-	ctrl_data |= CYBER_DMA_LED;
-	((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return ((amiga_custom.intenar) & IF_PORTS);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if(write){
-		dma_init_read(esp, addr, count);
-	} else {
-		dma_init_write(esp, addr, count);
-	}
-}
-
-#define HOSTS_C
-
-int cyber_esp_release(struct Scsi_Host *instance)
-{
-#ifdef MODULE
-	unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
-
-	esp_deallocate((struct NCR_ESP *)instance->hostdata);
-	esp_release();
-	release_mem_region(address, sizeof(struct ESP_regs));
-	free_irq(IRQ_AMIGA_PORTS, esp_intr);
-#endif
-	return 1;
-}
-
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp-cyberstorm",
-	.proc_info		= esp_proc_info,
-	.name			= "CyberStorm SCSI",
-	.detect			= cyber_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= cyber_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
deleted file mode 100644
index e336e85..0000000
--- a/drivers/scsi/cyberstormII.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/* cyberstormII.c: Driver for CyberStorm SCSI Mk II
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * This driver is based on cyberstorm.c
- */
-
-/* TODO:
- *
- * 1) Figure out how to make a cleaner merge with the sparc driver with regard
- *    to the caches and the Sparc MMU mapping.
- * 2) Make as few routines required outside the generic driver. A lot of the
- *    routines in this file used to be inline!
- */
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#include <asm/pgtable.h>
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define CYBERII_ESP_ADDR 0x1ff03
-#define CYBERII_DMA_ADDR 0x1ff43
-
-
-/* The CyberStorm II DMA interface */
-struct cyberII_dma_registers {
-	volatile unsigned char cond_reg;        /* DMA cond    (ro)  [0x000] */
-#define ctrl_reg  cond_reg			/* DMA control (wo)  [0x000] */
-	unsigned char dmapad4[0x3f];
-	volatile unsigned char dma_addr0;	/* DMA address (MSB) [0x040] */
-	unsigned char dmapad1[3];
-	volatile unsigned char dma_addr1;	/* DMA address       [0x044] */
-	unsigned char dmapad2[3];
-	volatile unsigned char dma_addr2;	/* DMA address       [0x048] */
-	unsigned char dmapad3[3];
-	volatile unsigned char dma_addr3;	/* DMA address (LSB) [0x04c] */
-};
-
-/* DMA control bits */
-#define CYBERII_DMA_LED    0x02	/* HD led control 1 = on */
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static void dma_led_off(struct NCR_ESP *esp);
-static void dma_led_on(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are transferred to the ESP chip
-				 * via PIO.
-				 */
-
-/***************************************************************** Detection */
-int __init cyberII_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	struct zorro_dev *z = NULL;
-	unsigned long address;
-	struct ESP_regs *eregs;
-
-	if ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, z))) {
-	    unsigned long board = z->resource.start;
-	    if (request_mem_region(board+CYBERII_ESP_ADDR,
-				   sizeof(struct ESP_regs), "NCR53C9x")) {
-		/* Do some magic to figure out if the CyberStorm Mk II
-		 * is equipped with a SCSI controller
-		 */
-		address = (unsigned long)ZTWO_VADDR(board);
-		eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR);
-
-		esp = esp_allocate(tpnt, (void *)board + CYBERII_ESP_ADDR, 0);
-
-		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
-		udelay(5);
-		if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7)) {
-			esp_deallocate(esp);
-			scsi_unregister(esp->ehost);
-			release_mem_region(board+CYBERII_ESP_ADDR,
-					   sizeof(struct ESP_regs));
-			return 0; /* Bail out if address did not hold data */
-		}
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = 0;
-		esp->dma_invalidate = 0;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = 0;
-		esp->dma_led_on = &dma_led_on;
-		esp->dma_led_off = &dma_led_off;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-
-		/* SCSI chip speed */
-		esp->cfreq = 40000000;
-
-		/* The DMA registers on the CyberStorm are mapped
-		 * relative to the device (i.e. in the same Zorro
-		 * I/O block).
-		 */
-		esp->dregs = (void *)(address + CYBERII_DMA_ADDR);
-
-		/* ESP register base */
-		esp->eregs = eregs;
-		
-		/* Set the command buffer */
-		esp->esp_command = cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
-
-		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
-			    "CyberStorm SCSI Mk II", esp->ehost);
-
-		/* Figure out our scsi ID on the bus */
-		esp->scsi_id = 7;
-		
-		/* We don't have a differential SCSI-bus. */
-		esp->diff = 0;
-
-		esp_initialize(esp);
-
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-		return esps_in_use;
-	    }
-	}
-	return 0;
-}
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
-	 * the number of bytes sent (to the ESP chip) equals the number
-	 * of bytes in the FIFO - there is no buffering in the DMA controller.
-	 * XXXX Do I read this right? It is from host to ESP, right?
-	 */
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	/* I don't think there's any limit on the CyberDMA. So we use what
-	 * the ESP chip can handle (24 bit).
-	 */
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > 0x1000000)
-		sz = 0x1000000;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
-		esp->esp_id, ((struct cyberII_dma_registers *)
-			      (esp->dregs))->cond_reg));
-	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
-		amiga_custom.intreqr, amiga_custom.intenar));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct cyberII_dma_registers *dregs = 
-		(struct cyberII_dma_registers *) esp->dregs;
-
-	cache_clear(addr, length);
-
-	addr &= ~(1);
-	dregs->dma_addr0 = (addr >> 24) & 0xff;
-	dregs->dma_addr1 = (addr >> 16) & 0xff;
-	dregs->dma_addr2 = (addr >>  8) & 0xff;
-	dregs->dma_addr3 = (addr      ) & 0xff;
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct cyberII_dma_registers *dregs = 
-		(struct cyberII_dma_registers *) esp->dregs;
-
-	cache_push(addr, length);
-
-	addr |= 1;
-	dregs->dma_addr0 = (addr >> 24) & 0xff;
-	dregs->dma_addr1 = (addr >> 16) & 0xff;
-	dregs->dma_addr2 = (addr >>  8) & 0xff;
-	dregs->dma_addr3 = (addr      ) & 0xff;
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(esp->irq);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	/* It's important to check the DMA IRQ bit in the correct way! */
-	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
-}
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-	((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg &= ~CYBERII_DMA_LED;
-}
-
-static void dma_led_on(struct NCR_ESP *esp)
-{
-	((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg |= CYBERII_DMA_LED;
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return ((amiga_custom.intenar) & IF_PORTS);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if(write){
-		dma_init_read(esp, addr, count);
-	} else {
-		dma_init_write(esp, addr, count);
-	}
-}
-
-#define HOSTS_C
-
-int cyberII_esp_release(struct Scsi_Host *instance)
-{
-#ifdef MODULE
-	unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
-
-	esp_deallocate((struct NCR_ESP *)instance->hostdata); 
-	esp_release();
-	release_mem_region(address, sizeof(struct ESP_regs));
-	free_irq(IRQ_AMIGA_PORTS, esp_intr);
-#endif
-	return 1;
-}
-
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp-cyberstormII",
-	.proc_info		= esp_proc_info,
-	.name			= "CyberStorm Mk II SCSI",
-	.detect			= cyberII_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= cyberII_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 22ef371..e351db6 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4267,7 +4267,7 @@
 	const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 	int srb_idx = 0;
 	unsigned i = 0;
-	struct SGentry *ptr;
+	struct SGentry *uninitialized_var(ptr);
 
 	for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
 		acb->srb_array[i].segment_x = NULL;
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
deleted file mode 100644
index d42ad66..0000000
--- a/drivers/scsi/dec_esp.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * dec_esp.c: Driver for SCSI chips on IOASIC based TURBOchannel DECstations
- *            and TURBOchannel PMAZ-A cards
- *
- * TURBOchannel changes by Harald Koerfgen
- * PMAZ-A support by David Airlie
- *
- * based on jazz_esp.c:
- * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- *
- * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
- *
- * 20000819 - Small PMAZ-AA fixes by Florian Lohoff <flo@rfc822.org>
- *            Be warned the PMAZ-AA works currently as a single card.
- *            Dont try to put multiple cards in one machine - They are
- *            both detected but it may crash under high load garbling your
- *            data.
- * 20001005	- Initialization fixes for 2.4.0-test9
- * 			  Florian Lohoff <flo@rfc822.org>
- *
- *	Copyright (C) 2002, 2003, 2005, 2006  Maciej W. Rozycki
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/stat.h>
-#include <linux/tc.h>
-
-#include <asm/dma.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-
-#include <asm/dec/interrupts.h>
-#include <asm/dec/ioasic.h>
-#include <asm/dec/ioasic_addrs.h>
-#include <asm/dec/ioasic_ints.h>
-#include <asm/dec/machtype.h>
-#include <asm/dec/system.h>
-
-#define DEC_SCSI_SREG 0
-#define DEC_SCSI_DMAREG 0x40000
-#define DEC_SCSI_SRAM 0x80000
-#define DEC_SCSI_DIAG 0xC0000
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static void dma_drain(struct NCR_ESP *esp);
-static int  dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length);
-static void dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, u32 addr, int count, int write);
-static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp);
-static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, struct scsi_cmnd * sp);
-static void dma_advance_sg(struct scsi_cmnd * sp);
-
-static void pmaz_dma_drain(struct NCR_ESP *esp);
-static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length);
-static void pmaz_dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length);
-static void pmaz_dma_ints_off(struct NCR_ESP *esp);
-static void pmaz_dma_ints_on(struct NCR_ESP *esp);
-static void pmaz_dma_setup(struct NCR_ESP *esp, u32 addr, int count, int write);
-static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp);
-
-#define TC_ESP_RAM_SIZE 0x20000
-#define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1))
-#define ESP_NCMD 7
-
-#define TC_ESP_DMAR_MASK  0x1ffff
-#define TC_ESP_DMAR_WRITE 0x80000000
-#define TC_ESP_DMA_ADDR(x) ((unsigned)(x) & TC_ESP_DMAR_MASK)
-
-u32 esp_virt_buffer;
-int scsi_current_length;
-
-volatile unsigned char cmd_buffer[16];
-volatile unsigned char pmaz_cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are trasfered to the ESP chip
-				 * via PIO.
-				 */
-
-static irqreturn_t scsi_dma_merr_int(int, void *);
-static irqreturn_t scsi_dma_err_int(int, void *);
-static irqreturn_t scsi_dma_int(int, void *);
-
-static struct scsi_host_template dec_esp_template = {
-	.module			= THIS_MODULE,
-	.name			= "NCR53C94",
-	.info			= esp_info,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.proc_info		= esp_proc_info,
-	.proc_name		= "dec_esp",
-	.can_queue		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= DISABLE_CLUSTERING,
-};
-
-static struct NCR_ESP *dec_esp_platform;
-
-/***************************************************************** Detection */
-static int dec_esp_platform_probe(void)
-{
-	struct NCR_ESP *esp;
-	int err = 0;
-
-	if (IOASIC) {
-		esp = esp_allocate(&dec_esp_template, NULL, 1);
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = &dma_drain;
-		esp->dma_invalidate = 0;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = 0;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-		esp->dma_led_off = 0;
-		esp->dma_led_on = 0;
-
-		/* virtual DMA functions */
-		esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
-		esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
-		esp->dma_mmu_release_scsi_one = 0;
-		esp->dma_mmu_release_scsi_sgl = 0;
-		esp->dma_advance_sg = &dma_advance_sg;
-
-
-		/* SCSI chip speed */
-		esp->cfreq = 25000000;
-
-		esp->dregs = 0;
-
-		/* ESP register base */
-		esp->eregs = (void *)CKSEG1ADDR(dec_kn_slot_base +
-						IOASIC_SCSI);
-
-		/* Set the command buffer */
-		esp->esp_command = (volatile unsigned char *) cmd_buffer;
-
-		/* get virtual dma address for command buffer */
-		esp->esp_command_dvma = virt_to_phys(cmd_buffer);
-
-		esp->irq = dec_interrupt[DEC_IRQ_ASC];
-
-		esp->scsi_id = 7;
-
-		/* Check for differential SCSI-bus */
-		esp->diff = 0;
-
-		err = request_irq(esp->irq, esp_intr, IRQF_DISABLED,
-				  "ncr53c94", esp->ehost);
-		if (err)
-			goto err_alloc;
-		err = request_irq(dec_interrupt[DEC_IRQ_ASC_MERR],
-				  scsi_dma_merr_int, IRQF_DISABLED,
-				  "ncr53c94 error", esp->ehost);
-		if (err)
-			goto err_irq;
-		err = request_irq(dec_interrupt[DEC_IRQ_ASC_ERR],
-				  scsi_dma_err_int, IRQF_DISABLED,
-				  "ncr53c94 overrun", esp->ehost);
-		if (err)
-			goto err_irq_merr;
-		err = request_irq(dec_interrupt[DEC_IRQ_ASC_DMA], scsi_dma_int,
-				  IRQF_DISABLED, "ncr53c94 dma", esp->ehost);
-		if (err)
-			goto err_irq_err;
-
-		esp_initialize(esp);
-
-		err = scsi_add_host(esp->ehost, NULL);
-		if (err) {
-			printk(KERN_ERR "ESP: Unable to register adapter\n");
-			goto err_irq_dma;
-		}
-
-		scsi_scan_host(esp->ehost);
-
-		dec_esp_platform = esp;
-	}
-
-	return 0;
-
-err_irq_dma:
-	free_irq(dec_interrupt[DEC_IRQ_ASC_DMA], esp->ehost);
-err_irq_err:
-	free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], esp->ehost);
-err_irq_merr:
-	free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], esp->ehost);
-err_irq:
-	free_irq(esp->irq, esp->ehost);
-err_alloc:
-	esp_deallocate(esp);
-	scsi_host_put(esp->ehost);
-	return err;
-}
-
-static int __init dec_esp_probe(struct device *dev)
-{
-	struct NCR_ESP *esp;
-	resource_size_t start, len;
-	int err;
-
-	esp = esp_allocate(&dec_esp_template,  NULL, 1);
-
-	dev_set_drvdata(dev, esp);
-
-	start = to_tc_dev(dev)->resource.start;
-	len = to_tc_dev(dev)->resource.end - start + 1;
-
-	if (!request_mem_region(start, len, dev->bus_id)) {
-		printk(KERN_ERR "%s: Unable to reserve MMIO resource\n",
-		       dev->bus_id);
-		err = -EBUSY;
-		goto err_alloc;
-	}
-
-	/* Store base addr into esp struct.  */
-	esp->slot = start;
-
-	esp->dregs = 0;
-	esp->eregs = (void *)CKSEG1ADDR(start + DEC_SCSI_SREG);
-	esp->do_pio_cmds = 1;
-
-	/* Set the command buffer.  */
-	esp->esp_command = (volatile unsigned char *)pmaz_cmd_buffer;
-
-	/* Get virtual dma address for command buffer.  */
-	esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer);
-
-	esp->cfreq = tc_get_speed(to_tc_dev(dev)->bus);
-
-	esp->irq = to_tc_dev(dev)->interrupt;
-
-	/* Required functions.  */
-	esp->dma_bytes_sent = &dma_bytes_sent;
-	esp->dma_can_transfer = &dma_can_transfer;
-	esp->dma_dump_state = &dma_dump_state;
-	esp->dma_init_read = &pmaz_dma_init_read;
-	esp->dma_init_write = &pmaz_dma_init_write;
-	esp->dma_ints_off = &pmaz_dma_ints_off;
-	esp->dma_ints_on = &pmaz_dma_ints_on;
-	esp->dma_irq_p = &dma_irq_p;
-	esp->dma_ports_p = &dma_ports_p;
-	esp->dma_setup = &pmaz_dma_setup;
-
-	/* Optional functions.  */
-	esp->dma_barrier = 0;
-	esp->dma_drain = &pmaz_dma_drain;
-	esp->dma_invalidate = 0;
-	esp->dma_irq_entry = 0;
-	esp->dma_irq_exit = 0;
-	esp->dma_poll = 0;
-	esp->dma_reset = 0;
-	esp->dma_led_off = 0;
-	esp->dma_led_on = 0;
-
-	esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one;
-	esp->dma_mmu_get_scsi_sgl = 0;
-	esp->dma_mmu_release_scsi_one = 0;
-	esp->dma_mmu_release_scsi_sgl = 0;
-	esp->dma_advance_sg = 0;
-
-	err = request_irq(esp->irq, esp_intr, IRQF_DISABLED, "PMAZ_AA",
-			  esp->ehost);
-	if (err) {
-		printk(KERN_ERR "%s: Unable to get IRQ %d\n",
-		       dev->bus_id, esp->irq);
-		goto err_resource;
-	}
-
-	esp->scsi_id = 7;
-	esp->diff = 0;
-	esp_initialize(esp);
-
-	err = scsi_add_host(esp->ehost, dev);
-	if (err) {
-		printk(KERN_ERR "%s: Unable to register adapter\n",
-		       dev->bus_id);
-		goto err_irq;
-	}
-
-	scsi_scan_host(esp->ehost);
-
-	return 0;
-
-err_irq:
-	free_irq(esp->irq, esp->ehost);
-
-err_resource:
-	release_mem_region(start, len);
-
-err_alloc:
-	esp_deallocate(esp);
-	scsi_host_put(esp->ehost);
-	return err;
-}
-
-static void __exit dec_esp_platform_remove(void)
-{
-	struct NCR_ESP *esp = dec_esp_platform;
-
-	free_irq(esp->irq, esp->ehost);
-	esp_deallocate(esp);
-	scsi_host_put(esp->ehost);
-	dec_esp_platform = NULL;
-}
-
-static void __exit dec_esp_remove(struct device *dev)
-{
-	struct NCR_ESP *esp = dev_get_drvdata(dev);
-
-	free_irq(esp->irq, esp->ehost);
-	esp_deallocate(esp);
-	scsi_host_put(esp->ehost);
-}
-
-
-/************************************************************* DMA Functions */
-static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id)
-{
-	printk("Got unexpected SCSI DMA Interrupt! < ");
-	printk("SCSI_DMA_MEMRDERR ");
-	printk(">\n");
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t scsi_dma_err_int(int irq, void *dev_id)
-{
-	/* empty */
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t scsi_dma_int(int irq, void *dev_id)
-{
-	u32 scsi_next_ptr;
-
-	scsi_next_ptr = ioasic_read(IO_REG_SCSI_DMA_P);
-
-	/* next page */
-	scsi_next_ptr = (((scsi_next_ptr >> 3) + PAGE_SIZE) & PAGE_MASK) << 3;
-	ioasic_write(IO_REG_SCSI_DMA_BP, scsi_next_ptr);
-	fast_iob();
-
-	return IRQ_HANDLED;
-}
-
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	return fifo_count;
-}
-
-static void dma_drain(struct NCR_ESP *esp)
-{
-	u32 nw, data0, data1, scsi_data_ptr;
-	u16 *p;
-
-	nw = ioasic_read(IO_REG_SCSI_SCR);
-
-	/*
-	 * Is there something in the dma buffers left?
-	 */
-	if (nw) {
-		scsi_data_ptr = ioasic_read(IO_REG_SCSI_DMA_P) >> 3;
-		p = phys_to_virt(scsi_data_ptr);
-		switch (nw) {
-		case 1:
-			data0 = ioasic_read(IO_REG_SCSI_SDR0);
-			p[0] = data0 & 0xffff;
-			break;
-		case 2:
-			data0 = ioasic_read(IO_REG_SCSI_SDR0);
-			p[0] = data0 & 0xffff;
-			p[1] = (data0 >> 16) & 0xffff;
-			break;
-		case 3:
-			data0 = ioasic_read(IO_REG_SCSI_SDR0);
-			data1 = ioasic_read(IO_REG_SCSI_SDR1);
-			p[0] = data0 & 0xffff;
-			p[1] = (data0 >> 16) & 0xffff;
-			p[2] = data1 & 0xffff;
-			break;
-		default:
-			printk("Strange: %d words in dma buffer left\n", nw);
-			break;
-		}
-	}
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd * sp)
-{
-	return sp->SCp.this_residual;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-}
-
-static void dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length)
-{
-	u32 scsi_next_ptr, ioasic_ssr;
-	unsigned long flags;
-
-	if (vaddress & 3)
-		panic("dec_esp.c: unable to handle partial word transfers, yet...");
-
-	dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length);
-
-	spin_lock_irqsave(&ioasic_ssr_lock, flags);
-
-	fast_mb();
-	ioasic_ssr = ioasic_read(IO_REG_SSR);
-
-	ioasic_ssr &= ~IO_SSR_SCSI_DMA_EN;
-	ioasic_write(IO_REG_SSR, ioasic_ssr);
-
-	fast_wmb();
-	ioasic_write(IO_REG_SCSI_SCR, 0);
-	ioasic_write(IO_REG_SCSI_DMA_P, vaddress << 3);
-
-	/* prepare for next page */
-	scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
-	ioasic_write(IO_REG_SCSI_DMA_BP, scsi_next_ptr);
-
-	ioasic_ssr |= (IO_SSR_SCSI_DMA_DIR | IO_SSR_SCSI_DMA_EN);
-	fast_wmb();
-	ioasic_write(IO_REG_SSR, ioasic_ssr);
-
-	fast_iob();
-	spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
-}
-
-static void dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length)
-{
-	u32 scsi_next_ptr, ioasic_ssr;
-	unsigned long flags;
-
-	if (vaddress & 3)
-		panic("dec_esp.c: unable to handle partial word transfers, yet...");
-
-	dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length);
-
-	spin_lock_irqsave(&ioasic_ssr_lock, flags);
-
-	fast_mb();
-	ioasic_ssr = ioasic_read(IO_REG_SSR);
-
-	ioasic_ssr &= ~(IO_SSR_SCSI_DMA_DIR | IO_SSR_SCSI_DMA_EN);
-	ioasic_write(IO_REG_SSR, ioasic_ssr);
-
-	fast_wmb();
-	ioasic_write(IO_REG_SCSI_SCR, 0);
-	ioasic_write(IO_REG_SCSI_DMA_P, vaddress << 3);
-
-	/* prepare for next page */
-	scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
-	ioasic_write(IO_REG_SCSI_DMA_BP, scsi_next_ptr);
-
-	ioasic_ssr |= IO_SSR_SCSI_DMA_EN;
-	fast_wmb();
-	ioasic_write(IO_REG_SSR, ioasic_ssr);
-
-	fast_iob();
-	spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(dec_interrupt[DEC_IRQ_ASC_DMA]);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(dec_interrupt[DEC_IRQ_ASC_DMA]);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	return (esp->eregs->esp_status & ESP_STAT_INTR);
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	/*
-	 * FIXME: what's this good for?
-	 */
-	return 1;
-}
-
-static void dma_setup(struct NCR_ESP *esp, u32 addr, int count, int write)
-{
-	/*
-	 * DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if (write)
-		dma_init_read(esp, addr, count);
-	else
-		dma_init_write(esp, addr, count);
-}
-
-static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp)
-{
-	sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);
-}
-
-static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, struct scsi_cmnd * sp)
-{
-	int sz = sp->SCp.buffers_residual;
-	struct scatterlist *sg = sp->SCp.buffer;
-
-	while (sz >= 0) {
-		sg[sz].dma_address = page_to_phys(sg[sz].page) + sg[sz].offset;
-		sz--;
-	}
-	sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
-}
-
-static void dma_advance_sg(struct scsi_cmnd * sp)
-{
-	sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
-}
-
-static void pmaz_dma_drain(struct NCR_ESP *esp)
-{
-	memcpy(phys_to_virt(esp_virt_buffer),
-	       (void *)CKSEG1ADDR(esp->slot + DEC_SCSI_SRAM +
-				  ESP_TGT_DMA_SIZE),
-	       scsi_current_length);
-}
-
-static void pmaz_dma_init_read(struct NCR_ESP *esp, u32 vaddress, int length)
-{
-	volatile u32 *dmareg =
-		(volatile u32 *)CKSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
-
-	if (length > ESP_TGT_DMA_SIZE)
-		length = ESP_TGT_DMA_SIZE;
-
-	*dmareg = TC_ESP_DMA_ADDR(ESP_TGT_DMA_SIZE);
-
-	iob();
-
-	esp_virt_buffer = vaddress;
-	scsi_current_length = length;
-}
-
-static void pmaz_dma_init_write(struct NCR_ESP *esp, u32 vaddress, int length)
-{
-	volatile u32 *dmareg =
-		(volatile u32 *)CKSEG1ADDR(esp->slot + DEC_SCSI_DMAREG);
-
-	memcpy((void *)CKSEG1ADDR(esp->slot + DEC_SCSI_SRAM +
-				  ESP_TGT_DMA_SIZE),
-	       phys_to_virt(vaddress), length);
-
-	wmb();
-	*dmareg = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(ESP_TGT_DMA_SIZE);
-
-	iob();
-}
-
-static void pmaz_dma_ints_off(struct NCR_ESP *esp)
-{
-}
-
-static void pmaz_dma_ints_on(struct NCR_ESP *esp)
-{
-}
-
-static void pmaz_dma_setup(struct NCR_ESP *esp, u32 addr, int count, int write)
-{
-	/*
-	 * DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if (write)
-		pmaz_dma_init_read(esp, addr, count);
-	else
-		pmaz_dma_init_write(esp, addr, count);
-}
-
-static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp)
-{
-	sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer);
-}
-
-
-#ifdef CONFIG_TC
-static int __init dec_esp_tc_probe(struct device *dev);
-static int __exit dec_esp_tc_remove(struct device *dev);
-
-static const struct tc_device_id dec_esp_tc_table[] = {
-        { "DEC     ", "PMAZ-AA " },
-        { }
-};
-MODULE_DEVICE_TABLE(tc, dec_esp_tc_table);
-
-static struct tc_driver dec_esp_tc_driver = {
-        .id_table       = dec_esp_tc_table,
-        .driver         = {
-                .name   = "dec_esp",
-                .bus    = &tc_bus_type,
-                .probe  = dec_esp_tc_probe,
-                .remove = __exit_p(dec_esp_tc_remove),
-        },
-};
-
-static int __init dec_esp_tc_probe(struct device *dev)
-{
-	int status = dec_esp_probe(dev);
-	if (!status)
-		get_device(dev);
-	return status;
-}
-
-static int __exit dec_esp_tc_remove(struct device *dev)
-{
-	put_device(dev);
-	dec_esp_remove(dev);
-	return 0;
-}
-#endif
-
-static int __init dec_esp_init(void)
-{
-	int status;
-
-	status = tc_register_driver(&dec_esp_tc_driver);
-	if (!status)
-		dec_esp_platform_probe();
-
-	if (nesps) {
-		pr_info("ESP: Total of %d ESP hosts found, "
-			"%d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-	}
-
-	return status;
-}
-
-static void __exit dec_esp_exit(void)
-{
-	dec_esp_platform_remove();
-	tc_unregister_driver(&dec_esp_tc_driver);
-}
-
-
-module_init(dec_esp_init);
-module_exit(dec_esp_exit);
diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
deleted file mode 100644
index 4266a21..0000000
--- a/drivers/scsi/fastlane.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/* fastlane.c: Driver for Phase5's Fastlane SCSI Controller.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * This driver is based on the CyberStorm driver, hence the occasional
- * reference to CyberStorm.
- *
- * Betatesting & crucial adjustments by
- *        Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
- *
- */
-
-/* TODO:
- *
- * o According to the doc from laire, it is required to reset the DMA when
- *   the transfer is done. ATM we reset DMA just before every new 
- *   dma_init_(read|write).
- *
- * 1) Figure out how to make a cleaner merge with the sparc driver with regard
- *    to the caches and the Sparc MMU mapping.
- * 2) Make as few routines required outside the generic driver. A lot of the
- *    routines in this file used to be inline!
- */
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <linux/zorro.h>
-#include <asm/irq.h>
-
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#include <asm/pgtable.h>
-
-/* Such day has just come... */
-#if 0
-/* Let this defined unless you really need to enable DMA IRQ one day */
-#define NODMAIRQ
-#endif
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define FASTLANE_ESP_ADDR 0x1000001
-#define FASTLANE_DMA_ADDR 0x1000041
-
-
-/* The Fastlane DMA interface */
-struct fastlane_dma_registers {
-	volatile unsigned char cond_reg;	/* DMA status  (ro) [0x0000] */
-#define ctrl_reg  cond_reg			/* DMA control (wo) [0x0000] */
-	unsigned char dmapad1[0x3f];
-	volatile unsigned char clear_strobe;    /* DMA clear   (wo) [0x0040] */
-};
-
-
-/* DMA status bits */
-#define FASTLANE_DMA_MINT  0x80
-#define FASTLANE_DMA_IACT  0x40
-#define FASTLANE_DMA_CREQ  0x20
-
-/* DMA control bits */
-#define FASTLANE_DMA_FCODE 0xa0
-#define FASTLANE_DMA_MASK  0xf3
-#define FASTLANE_DMA_LED   0x10	/* HD led control 1 = on */
-#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */
-#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */
-#define FASTLANE_DMA_EDI   0x02	/* Enable DMA IRQ ? */
-#define FASTLANE_DMA_ESI   0x01	/* Enable SCSI IRQ */
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddr, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static void dma_irq_exit(struct NCR_ESP *esp);
-static void dma_led_off(struct NCR_ESP *esp);
-static void dma_led_on(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-
-static unsigned char ctrl_data = 0;	/* Keep backup of the stuff written
-				 * to ctrl_reg. Always write a copy
-				 * to this register when writing to
-				 * the hardware register!
-				 */
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are transferred to the ESP chip
-				 * via PIO.
-				 */
-
-static inline void dma_clear(struct NCR_ESP *esp)
-{
-	struct fastlane_dma_registers *dregs =
-		(struct fastlane_dma_registers *) (esp->dregs);
-	unsigned long *t;
-
-	ctrl_data = (ctrl_data & FASTLANE_DMA_MASK);
-	dregs->ctrl_reg = ctrl_data;
-
-	t = (unsigned long *)(esp->edev);
-
-	dregs->clear_strobe = 0;
-	*t = 0 ;
-}
-
-/***************************************************************** Detection */
-int __init fastlane_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	struct zorro_dev *z = NULL;
-	unsigned long address;
-
-	if ((z = zorro_find_device(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, z))) {
-	    unsigned long board = z->resource.start;
-	    if (request_mem_region(board+FASTLANE_ESP_ADDR,
-				   sizeof(struct ESP_regs), "NCR53C9x")) {
-		/* Check if this is really a fastlane controller. The problem
-		 * is that also the cyberstorm and blizzard controllers use
-		 * this ID value. Fortunately only Fastlane maps in Z3 space
-		 */
-		if (board < 0x1000000) {
-			goto err_release;
-		}
-		esp = esp_allocate(tpnt, (void *)board + FASTLANE_ESP_ADDR, 0);
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = 0;
-		esp->dma_invalidate = 0;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = &dma_irq_exit;
-		esp->dma_led_on = &dma_led_on;
-		esp->dma_led_off = &dma_led_off;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-
-		/* Initialize the portBits (enable IRQs) */
-		ctrl_data = (FASTLANE_DMA_FCODE |
-#ifndef NODMAIRQ
-			     FASTLANE_DMA_EDI |
-#endif
-			     FASTLANE_DMA_ESI);
-			
-
-		/* SCSI chip clock */
-		esp->cfreq = 40000000;
-
-
-		/* Map the physical address space into virtual kernel space */
-		address = (unsigned long)
-			z_ioremap(board, z->resource.end-board+1);
-
-		if(!address){
-			printk("Could not remap Fastlane controller memory!");
-			goto err_unregister;
-		}
-
-
-		/* The DMA registers on the Fastlane are mapped
-		 * relative to the device (i.e. in the same Zorro
-		 * I/O block).
-		 */
-		esp->dregs = (void *)(address + FASTLANE_DMA_ADDR);
-
-		/* ESP register base */
-		esp->eregs = (struct ESP_regs *)(address + FASTLANE_ESP_ADDR);
-
-		/* Board base */
-		esp->edev = (void *) address;
-		
-		/* Set the command buffer */
-		esp->esp_command = cmd_buffer;
-		esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
-
-		esp->irq = IRQ_AMIGA_PORTS;
-		esp->slot = board+FASTLANE_ESP_ADDR;
-		if (request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
-				"Fastlane SCSI", esp->ehost)) {
-			printk(KERN_WARNING "Fastlane: Could not get IRQ%d, aborting.\n", IRQ_AMIGA_PORTS);
-			goto err_unmap;
-		}			
-
-		/* Controller ID */
-		esp->scsi_id = 7;
-		
-		/* We don't have a differential SCSI-bus. */
-		esp->diff = 0;
-
-		dma_clear(esp);
-		esp_initialize(esp);
-
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
-		esps_running = esps_in_use;
-		return esps_in_use;
-	    }
-	}
-	return 0;
-
- err_unmap:
-	z_iounmap((void *)address);
- err_unregister:
-	scsi_unregister (esp->ehost);
- err_release:
-	release_mem_region(z->resource.start+FASTLANE_ESP_ADDR,
-			   sizeof(struct ESP_regs));
-	return 0;
-}
-
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Since the Fastlane DMA is fully dedicated to the ESP chip,
-	 * the number of bytes sent (to the ESP chip) equals the number
-	 * of bytes in the FIFO - there is no buffering in the DMA controller.
-	 * XXXX Do I read this right? It is from host to ESP, right?
-	 */
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > 0xfffc)
-		sz = 0xfffc;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
-		esp->esp_id, ((struct fastlane_dma_registers *)
-			      (esp->dregs))->cond_reg));
-	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
-		amiga_custom.intreqr, amiga_custom.intenar));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct fastlane_dma_registers *dregs = 
-		(struct fastlane_dma_registers *) (esp->dregs);
-	unsigned long *t;
-	
-	cache_clear(addr, length);
-
-	dma_clear(esp);
-
-	t = (unsigned long *)((addr & 0x00ffffff) + esp->edev);
-
-	dregs->clear_strobe = 0;
-	*t = addr;
-
-	ctrl_data = (ctrl_data & FASTLANE_DMA_MASK) | FASTLANE_DMA_ENABLE;
-	dregs->ctrl_reg = ctrl_data;
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	struct fastlane_dma_registers *dregs = 
-		(struct fastlane_dma_registers *) (esp->dregs);
-	unsigned long *t;
-
-	cache_push(addr, length);
-
-	dma_clear(esp);
-
-	t = (unsigned long *)((addr & 0x00ffffff) + (esp->edev));
-
-	dregs->clear_strobe = 0;
-	*t = addr;
-
-	ctrl_data = ((ctrl_data & FASTLANE_DMA_MASK) | 
-		     FASTLANE_DMA_ENABLE |
-		     FASTLANE_DMA_WRITE);
-	dregs->ctrl_reg = ctrl_data;
-}
-
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(esp->irq);
-}
-
-static void dma_irq_exit(struct NCR_ESP *esp)
-{
-	struct fastlane_dma_registers *dregs = 
-		(struct fastlane_dma_registers *) (esp->dregs);
-
-	dregs->ctrl_reg = ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI);
-#ifdef __mc68000__
-	nop();
-#endif
-	dregs->ctrl_reg = ctrl_data;
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	struct fastlane_dma_registers *dregs = 
-		(struct fastlane_dma_registers *) (esp->dregs);
-	unsigned char dma_status;
-
-	dma_status = dregs->cond_reg;
-
-	if(dma_status & FASTLANE_DMA_IACT)
-		return 0;	/* not our IRQ */
-
-	/* Return non-zero if ESP requested IRQ */
-	return (
-#ifndef NODMAIRQ
-	   (dma_status & FASTLANE_DMA_CREQ) &&
-#endif
-	   (!(dma_status & FASTLANE_DMA_MINT)) &&
-	   (esp_read(((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
-}
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-	ctrl_data &= ~FASTLANE_DMA_LED;
-	((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
-}
-
-static void dma_led_on(struct NCR_ESP *esp)
-{
-	ctrl_data |= FASTLANE_DMA_LED;
-	((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return ((amiga_custom.intenar) & IF_PORTS);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if(write){
-		dma_init_read(esp, addr, count);
-	} else {
-		dma_init_write(esp, addr, count);
-	}
-}
-
-#define HOSTS_C
-
-int fastlane_esp_release(struct Scsi_Host *instance)
-{
-#ifdef MODULE
-	unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
-	esp_deallocate((struct NCR_ESP *)instance->hostdata);
-	esp_release();
-	release_mem_region(address, sizeof(struct ESP_regs));
-	free_irq(IRQ_AMIGA_PORTS, esp_intr);
-#endif
-	return 1;
-}
-
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp-fastlane",
-	.proc_info		= esp_proc_info,
-	.name			= "Fastlane SCSI",
-	.detect			= fastlane_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= fastlane_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING
-};
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index b6f99df..8a178674 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -629,8 +629,9 @@
 	int rc;
 
 	if (tcp_conn->in.datalen) {
-		printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n",
-		       tcp_conn->in.datalen);
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "invalid R2t with datalen %d\n",
+				  tcp_conn->in.datalen);
 		return ISCSI_ERR_DATALEN;
 	}
 
@@ -644,8 +645,9 @@
 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
 
 	if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
-		printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in "
-		       "recovery...\n", ctask->itt);
+		iscsi_conn_printk(KERN_INFO, conn,
+				  "dropping R2T itt %d in recovery.\n",
+				  ctask->itt);
 		return 0;
 	}
 
@@ -655,7 +657,8 @@
 	r2t->exp_statsn = rhdr->statsn;
 	r2t->data_length = be32_to_cpu(rhdr->data_length);
 	if (r2t->data_length == 0) {
-		printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n");
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "invalid R2T with zero data len\n");
 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
 			    sizeof(void*));
 		return ISCSI_ERR_DATALEN;
@@ -668,9 +671,10 @@
 
 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
 	if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
-		printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at "
-		       "offset %u and total length %d\n", r2t->data_length,
-		       r2t->data_offset, scsi_bufflen(ctask->sc));
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "invalid R2T with data len %u at offset %u "
+				  "and total length %d\n", r2t->data_length,
+				  r2t->data_offset, scsi_bufflen(ctask->sc));
 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
 			    sizeof(void*));
 		return ISCSI_ERR_DATALEN;
@@ -736,8 +740,9 @@
 	/* verify PDU length */
 	tcp_conn->in.datalen = ntoh24(hdr->dlength);
 	if (tcp_conn->in.datalen > conn->max_recv_dlength) {
-		printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n",
-		       tcp_conn->in.datalen, conn->max_recv_dlength);
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "iscsi_tcp: datalen %d > %d\n",
+				  tcp_conn->in.datalen, conn->max_recv_dlength);
 		return ISCSI_ERR_DATALEN;
 	}
 
@@ -819,10 +824,12 @@
 		 * For now we fail until we find a vendor that needs it
 		 */
 		if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) {
-			printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
-			      "but conn buffer is only %u (opcode %0x)\n",
-			      tcp_conn->in.datalen,
-			      ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
+			iscsi_conn_printk(KERN_ERR, conn,
+					  "iscsi_tcp: received buffer of "
+					  "len %u but conn buffer is only %u "
+					  "(opcode %0x)\n",
+					  tcp_conn->in.datalen,
+					  ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
 			rc = ISCSI_ERR_PROTO;
 			break;
 		}
@@ -1496,30 +1503,25 @@
 	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
 						  CRYPTO_ALG_ASYNC);
 	tcp_conn->tx_hash.flags = 0;
-	if (IS_ERR(tcp_conn->tx_hash.tfm)) {
-		printk(KERN_ERR "Could not create connection due to crc32c "
-		       "loading error %ld. Make sure the crc32c module is "
-		       "built as a module or into the kernel\n",
-			PTR_ERR(tcp_conn->tx_hash.tfm));
+	if (IS_ERR(tcp_conn->tx_hash.tfm))
 		goto free_tcp_conn;
-	}
 
 	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
 						  CRYPTO_ALG_ASYNC);
 	tcp_conn->rx_hash.flags = 0;
-	if (IS_ERR(tcp_conn->rx_hash.tfm)) {
-		printk(KERN_ERR "Could not create connection due to crc32c "
-		       "loading error %ld. Make sure the crc32c module is "
-		       "built as a module or into the kernel\n",
-			PTR_ERR(tcp_conn->rx_hash.tfm));
+	if (IS_ERR(tcp_conn->rx_hash.tfm))
 		goto free_tx_tfm;
-	}
 
 	return cls_conn;
 
 free_tx_tfm:
 	crypto_free_hash(tcp_conn->tx_hash.tfm);
 free_tcp_conn:
+	iscsi_conn_printk(KERN_ERR, conn,
+			  "Could not create connection due to crc32c "
+			  "loading error. Make sure the crc32c "
+			  "module is built as a module or into the "
+			  "kernel\n");
 	kfree(tcp_conn);
 tcp_conn_alloc_fail:
 	iscsi_conn_teardown(cls_conn);
@@ -1627,7 +1629,8 @@
 	/* lookup for existing socket */
 	sock = sockfd_lookup((int)transport_eph, &err);
 	if (!sock) {
-		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "sockfd_lookup failed %d\n", err);
 		return -EEXIST;
 	}
 	/*
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 553168a..59f8445 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -160,7 +160,7 @@
 	hdr->opcode = ISCSI_OP_SCSI_CMD;
 	hdr->flags = ISCSI_ATTR_SIMPLE;
 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
-	hdr->itt = build_itt(ctask->itt, conn->id, session->age);
+	hdr->itt = build_itt(ctask->itt, session->age);
 	hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
 	hdr->cmdsn = cpu_to_be32(session->cmdsn);
 	session->cmdsn++;
@@ -416,8 +416,9 @@
 
 		if (datalen < 2) {
 invalid_datalen:
-			printk(KERN_ERR "iscsi: Got CHECK_CONDITION but "
-			       "invalid data buffer size of %d\n", datalen);
+			iscsi_conn_printk(KERN_ERR,  conn,
+					 "Got CHECK_CONDITION but invalid data "
+					 "buffer size of %d\n", datalen);
 			sc->result = DID_BAD_TARGET << 16;
 			goto out;
 		}
@@ -494,7 +495,7 @@
 
 	mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
 	if (!mtask) {
-		printk(KERN_ERR "Could not send nopout\n");
+		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
 		return;
 	}
 
@@ -522,9 +523,10 @@
 		if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
 			memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
 			itt = get_itt(rejected_pdu.itt);
-			printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected "
-				"due to DataDigest error.\n", itt,
-				rejected_pdu.opcode);
+			iscsi_conn_printk(KERN_ERR, conn,
+					  "itt 0x%x had pdu (op 0x%x) rejected "
+					  "due to DataDigest error.\n", itt,
+					  rejected_pdu.opcode);
 		}
 	}
 	return 0;
@@ -541,8 +543,8 @@
  * queuecommand or send generic. session lock must be held and verify
  * itt must have been called.
  */
-int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-			 char *data, int datalen)
+static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+				char *data, int datalen)
 {
 	struct iscsi_session *session = conn->session;
 	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
@@ -672,7 +674,6 @@
 
 	return rc;
 }
-EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
 
 int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 		       char *data, int datalen)
@@ -697,18 +698,13 @@
 	if (hdr->itt != RESERVED_ITT) {
 		if (((__force u32)hdr->itt & ISCSI_AGE_MASK) !=
 		    (session->age << ISCSI_AGE_SHIFT)) {
-			printk(KERN_ERR "iscsi: received itt %x expected "
-				"session age (%x)\n", (__force u32)hdr->itt,
-				session->age & ISCSI_AGE_MASK);
+			iscsi_conn_printk(KERN_ERR, conn,
+					  "received itt %x expected session "
+					  "age (%x)\n", (__force u32)hdr->itt,
+					  session->age & ISCSI_AGE_MASK);
 			return ISCSI_ERR_BAD_ITT;
 		}
 
-		if (((__force u32)hdr->itt & ISCSI_CID_MASK) !=
-		    (conn->id << ISCSI_CID_SHIFT)) {
-			printk(KERN_ERR "iscsi: received itt %x, expected "
-				"CID (%x)\n", (__force u32)hdr->itt, conn->id);
-			return ISCSI_ERR_BAD_ITT;
-		}
 		itt = get_itt(hdr->itt);
 	} else
 		itt = ~0U;
@@ -717,16 +713,17 @@
 		ctask = session->cmds[itt];
 
 		if (!ctask->sc) {
-			printk(KERN_INFO "iscsi: dropping ctask with "
-			       "itt 0x%x\n", ctask->itt);
+			iscsi_conn_printk(KERN_INFO, conn, "dropping ctask "
+					  "with itt 0x%x\n", ctask->itt);
 			/* force drop */
 			return ISCSI_ERR_NO_SCSI_CMD;
 		}
 
 		if (ctask->sc->SCp.phase != session->age) {
-			printk(KERN_ERR "iscsi: ctask's session age %d, "
-				"expected %d\n", ctask->sc->SCp.phase,
-				session->age);
+			iscsi_conn_printk(KERN_ERR, conn,
+					  "iscsi: ctask's session age %d, "
+					  "expected %d\n", ctask->sc->SCp.phase,
+					  session->age);
 			return ISCSI_ERR_SESSION_FAILED;
 		}
 	}
@@ -771,7 +768,7 @@
 	 */
 	nop->cmdsn = cpu_to_be32(session->cmdsn);
 	if (hdr->itt != RESERVED_ITT) {
-		hdr->itt = build_itt(mtask->itt, conn->id, session->age);
+		hdr->itt = build_itt(mtask->itt, session->age);
 		/*
 		 * TODO: We always use immediate, so we never hit this.
 		 * If we start to send tmfs or nops as non-immediate then
@@ -997,6 +994,7 @@
 	FAILURE_SESSION_IN_RECOVERY,
 	FAILURE_SESSION_RECOVERY_TIMEOUT,
 	FAILURE_SESSION_LOGGING_OUT,
+	FAILURE_SESSION_NOT_READY,
 };
 
 int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
@@ -1017,6 +1015,12 @@
 	session = iscsi_hostdata(host->hostdata);
 	spin_lock(&session->lock);
 
+	reason = iscsi_session_chkready(session_to_cls(session));
+	if (reason) {
+		sc->result = reason;
+		goto fault;
+	}
+
 	/*
 	 * ISCSI_STATE_FAILED is a temp. state. The recovery
 	 * code will decide what is best to do with command queued
@@ -1033,18 +1037,23 @@
 		switch (session->state) {
 		case ISCSI_STATE_IN_RECOVERY:
 			reason = FAILURE_SESSION_IN_RECOVERY;
-			goto reject;
+			sc->result = DID_IMM_RETRY << 16;
+			break;
 		case ISCSI_STATE_LOGGING_OUT:
 			reason = FAILURE_SESSION_LOGGING_OUT;
-			goto reject;
+			sc->result = DID_IMM_RETRY << 16;
+			break;
 		case ISCSI_STATE_RECOVERY_FAILED:
 			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+			sc->result = DID_NO_CONNECT << 16;
 			break;
 		case ISCSI_STATE_TERMINATE:
 			reason = FAILURE_SESSION_TERMINATE;
+			sc->result = DID_NO_CONNECT << 16;
 			break;
 		default:
 			reason = FAILURE_SESSION_FREED;
+			sc->result = DID_NO_CONNECT << 16;
 		}
 		goto fault;
 	}
@@ -1052,6 +1061,7 @@
 	conn = session->leadconn;
 	if (!conn) {
 		reason = FAILURE_SESSION_FREED;
+		sc->result = DID_NO_CONNECT << 16;
 		goto fault;
 	}
 
@@ -1091,9 +1101,7 @@
 
 fault:
 	spin_unlock(&session->lock);
-	printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
-	       sc->cmnd[0], reason);
-	sc->result = (DID_NO_CONNECT << 16);
+	debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
 	scsi_set_resid(sc, scsi_bufflen(sc));
 	sc->scsi_done(sc);
 	spin_lock(host->host_lock);
@@ -1160,7 +1168,8 @@
 	mutex_lock(&session->eh_mutex);
 	spin_lock_bh(&session->lock);
 	if (session->state == ISCSI_STATE_LOGGED_IN)
-		printk(KERN_INFO "iscsi: host reset succeeded\n");
+		iscsi_session_printk(KERN_INFO, session,
+				     "host reset succeeded\n");
 	else
 		goto failed;
 	spin_unlock_bh(&session->lock);
@@ -1239,7 +1248,8 @@
  * Fail commands. session lock held and recv side suspended and xmit
  * thread flushed
  */
-static void fail_all_commands(struct iscsi_conn *conn, unsigned lun)
+static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
+			      int error)
 {
 	struct iscsi_cmd_task *ctask, *tmp;
 
@@ -1251,7 +1261,7 @@
 		if (lun == ctask->sc->device->lun || lun == -1) {
 			debug_scsi("failing pending sc %p itt 0x%x\n",
 				   ctask->sc, ctask->itt);
-			fail_command(conn, ctask, DID_BUS_BUSY << 16);
+			fail_command(conn, ctask, error << 16);
 		}
 	}
 
@@ -1259,7 +1269,7 @@
 		if (lun == ctask->sc->device->lun || lun == -1) {
 			debug_scsi("failing requeued sc %p itt 0x%x\n",
 				   ctask->sc, ctask->itt);
-			fail_command(conn, ctask, DID_BUS_BUSY << 16);
+			fail_command(conn, ctask, error << 16);
 		}
 	}
 
@@ -1357,10 +1367,10 @@
 	last_recv = conn->last_recv;
 	if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
 			   jiffies)) {
-		printk(KERN_ERR "ping timeout of %d secs expired, "
-		       "last rx %lu, last ping %lu, now %lu\n",
-		       conn->ping_timeout, last_recv,
-		       conn->last_ping, jiffies);
+		iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
+				  "expired, last rx %lu, last ping %lu, "
+				  "now %lu\n", conn->ping_timeout, last_recv,
+				  conn->last_ping, jiffies);
 		spin_unlock(&session->lock);
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 		return;
@@ -1373,14 +1383,11 @@
 			iscsi_send_nopout(conn, NULL);
 		}
 		next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
-	} else {
+	} else
 		next_timeout = last_recv + timeout;
-	}
 
-	if (next_timeout) {
-		debug_scsi("Setting next tmo %lu\n", next_timeout);
-		mod_timer(&conn->transport_timer, next_timeout);
-	}
+	debug_scsi("Setting next tmo %lu\n", next_timeout);
+	mod_timer(&conn->transport_timer, next_timeout);
 done:
 	spin_unlock(&session->lock);
 }
@@ -1573,7 +1580,7 @@
 	/* need to grab the recv lock then session lock */
 	write_lock_bh(conn->recv_lock);
 	spin_lock(&session->lock);
-	fail_all_commands(conn, sc->device->lun);
+	fail_all_commands(conn, sc->device->lun, DID_ERROR);
 	conn->tmf_state = TMF_INITIAL;
 	spin_unlock(&session->lock);
 	write_unlock_bh(conn->recv_lock);
@@ -1944,9 +1951,10 @@
 		}
 		spin_unlock_irqrestore(session->host->host_lock, flags);
 		msleep_interruptible(500);
-		printk(KERN_INFO "iscsi: scsi conn_destroy(): host_busy %d "
-		       "host_failed %d\n", session->host->host_busy,
-		       session->host->host_failed);
+		iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
+				  "host_busy %d host_failed %d\n",
+				  session->host->host_busy,
+				  session->host->host_failed);
 		/*
 		 * force eh_abort() to unblock
 		 */
@@ -1975,27 +1983,28 @@
 	struct iscsi_session *session = conn->session;
 
 	if (!session) {
-		printk(KERN_ERR "iscsi: can't start unbound connection\n");
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "can't start unbound connection\n");
 		return -EPERM;
 	}
 
 	if ((session->imm_data_en || !session->initial_r2t_en) &&
 	     session->first_burst > session->max_burst) {
-		printk("iscsi: invalid burst lengths: "
-		       "first_burst %d max_burst %d\n",
-		       session->first_burst, session->max_burst);
+		iscsi_conn_printk(KERN_INFO, conn, "invalid burst lengths: "
+				  "first_burst %d max_burst %d\n",
+				  session->first_burst, session->max_burst);
 		return -EINVAL;
 	}
 
 	if (conn->ping_timeout && !conn->recv_timeout) {
-		printk(KERN_ERR "iscsi: invalid recv timeout of zero "
-		      "Using 5 seconds\n.");
+		iscsi_conn_printk(KERN_ERR, conn, "invalid recv timeout of "
+				  "zero. Using 5 seconds\n.");
 		conn->recv_timeout = 5;
 	}
 
 	if (conn->recv_timeout && !conn->ping_timeout) {
-		printk(KERN_ERR "iscsi: invalid ping timeout of zero "
-		      "Using 5 seconds.\n");
+		iscsi_conn_printk(KERN_ERR, conn, "invalid ping timeout of "
+				  "zero. Using 5 seconds.\n");
 		conn->ping_timeout = 5;
 	}
 
@@ -2019,11 +2028,9 @@
 		conn->stop_stage = 0;
 		conn->tmf_state = TMF_INITIAL;
 		session->age++;
-		spin_unlock_bh(&session->lock);
-
-		iscsi_unblock_session(session_to_cls(session));
-		wake_up(&conn->ehwait);
-		return 0;
+		if (session->age == 16)
+			session->age = 0;
+		break;
 	case STOP_CONN_TERM:
 		conn->stop_stage = 0;
 		break;
@@ -2032,6 +2039,8 @@
 	}
 	spin_unlock_bh(&session->lock);
 
+	iscsi_unblock_session(session_to_cls(session));
+	wake_up(&conn->ehwait);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_start);
@@ -2123,7 +2132,8 @@
 	 * flush queues.
 	 */
 	spin_lock_bh(&session->lock);
-	fail_all_commands(conn, -1);
+	fail_all_commands(conn, -1,
+			STOP_CONN_RECOVER ? DID_BUS_BUSY : DID_ERROR);
 	flush_control_queues(session, conn);
 	spin_unlock_bh(&session->lock);
 	mutex_unlock(&session->eh_mutex);
@@ -2140,7 +2150,8 @@
 		iscsi_start_session_recovery(session, conn, flag);
 		break;
 	default:
-		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "invalid stop flag %d\n", flag);
 	}
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_stop);
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
deleted file mode 100644
index bcb4902..0000000
--- a/drivers/scsi/mac_esp.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * 68k mac 53c9[46] scsi driver
- *
- * copyright (c) 1998, David Weis weisd3458@uni.edu
- *
- * debugging on Quadra 800 and 660AV Michael Schmitz, Dave Kilzer 7/98
- *
- * based loosely on cyber_esp.c
- */
-
-/* these are unused for now */
-#define myreadl(addr) (*(volatile unsigned int *) (addr))
-#define mywritel(b, addr) ((*(volatile unsigned int *) (addr)) = (b))
-
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <asm/io.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/macints.h>
-#include <asm/machw.h>
-#include <asm/mac_via.h>
-
-#include <asm/pgtable.h>
-
-#include <asm/macintosh.h>
-
-/* #define DEBUG_MAC_ESP */
-
-extern void esp_handle(struct NCR_ESP *esp);
-extern void mac_esp_intr(int irq, void *dev_id);
-
-static int  dma_bytes_sent(struct NCR_ESP * esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP * esp);
-static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length);
-static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length);
-static void dma_ints_off(struct NCR_ESP * esp);
-static void dma_ints_on(struct NCR_ESP * esp);
-static int  dma_irq_p(struct NCR_ESP * esp);
-static int  dma_irq_p_quick(struct NCR_ESP * esp);
-static void dma_led_off(struct NCR_ESP * esp);
-static void dma_led_on(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write);
-static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write);
-
-static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev);
-static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev);
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are transferred to the ESP chip
-				 * via PIO.
-				 */
-
-static int esp_initialized = 0;
-
-static int setup_num_esps = -1;
-static int setup_disconnect = -1;
-static int setup_nosync = -1;
-static int setup_can_queue = -1;
-static int setup_cmd_per_lun = -1;
-static int setup_sg_tablesize = -1;
-#ifdef SUPPORT_TAGS
-static int setup_use_tagged_queuing = -1;
-#endif
-static int setup_hostid = -1;
-
-/*
- * Experimental ESP inthandler; check macints.c to make sure dev_id is 
- * set up properly!
- */
-
-void mac_esp_intr(int irq, void *dev_id)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *) dev_id;
-	int irq_p = 0;
-
-	/* Handle the one ESP interrupt showing at this IRQ level. */
-	if(((esp)->irq & 0xff) == irq) {
-	/*
-	 * Debug ..
-	 */
-		irq_p = esp->dma_irq_p(esp);
-	 	printk("mac_esp: irq_p %x current %p disconnected %p\n",
-	 		irq_p, esp->current_SC, esp->disconnected_SC);
-	 		
-		/*
-		 * Mac: if we're here, it's an ESP interrupt for sure!
-		 */
-		if((esp->current_SC || esp->disconnected_SC)) {
-			esp->dma_ints_off(esp);
-
-			ESPIRQ(("I%d(", esp->esp_id));
-			esp_handle(esp);
-			ESPIRQ((")"));
-
-			esp->dma_ints_on(esp);
-		}
-	}
-}
-
-/*
- * Debug hooks; use for playing with the interrupt flag testing and interrupt
- * acknowledge on the various machines
- */
-
-void scsi_esp_polled(int irq, void *dev_id)
-{
-	if (esp_initialized == 0)
-		return;
-
-	mac_esp_intr(irq, dev_id);
-}
-
-void fake_intr(int irq, void *dev_id)
-{
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: got irq\n");
-#endif
-
-	mac_esp_intr(irq, dev_id);
-}
-
-irqreturn_t fake_drq(int irq, void *dev_id)
-{
-	printk("mac_esp: got drq\n");
-	return IRQ_HANDLED;
-}
-
-#define DRIVER_SETUP
-
-/*
- * Function : mac_esp_setup(char *str)
- *
- * Purpose : booter command line initialization of the overrides array,
- *
- * Inputs : str - parameters, separated by commas.
- *
- * Currently unused in the new driver; need to add settable parameters to the 
- * detect function.
- *
- */
-
-static int __init mac_esp_setup(char *str) {
-#ifdef DRIVER_SETUP
-	/* Format of mac53c9x parameter is:
-	 *   mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
-	 * Negative values mean don't change.
-	 */
-	
-	char *this_opt;
-	long opt;
-
-	this_opt = strsep (&str, ",");
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-
-		if (opt >= 0 && opt <= 2)
-			setup_num_esps = opt;
-		else if (opt > 2)
-			printk( "mac_esp_setup: invalid number of hosts %ld !\n", opt );
-
-		this_opt = strsep (&str, ",");
-	}
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-	
-		if (opt > 0)
-			setup_disconnect = opt;
-
-		this_opt = strsep (&str, ",");
-	}
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-
-		if (opt >= 0)
-			setup_nosync = opt;
-
-		this_opt = strsep (&str, ",");
-	}
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-
-		if (opt > 0)
-			setup_can_queue = opt;
-
-		this_opt = strsep (&str, ",");
-	}
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-
-		if (opt > 0)
-			setup_cmd_per_lun = opt;
-
-		this_opt = strsep (&str, ",");
-	}
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-
-		if (opt >= 0) {
-			setup_sg_tablesize = opt;
-			/* Must be <= SG_ALL (255) */
-			if (setup_sg_tablesize > SG_ALL)
-				setup_sg_tablesize = SG_ALL;
-		}
-
-		this_opt = strsep (&str, ",");
-	}
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-
-		/* Must be between 0 and 7 */
-		if (opt >= 0 && opt <= 7)
-			setup_hostid = opt;
-		else if (opt > 7)
-			printk( "mac_esp_setup: invalid host ID %ld !\n", opt);
-
-		this_opt = strsep (&str, ",");
-	}
-#ifdef SUPPORT_TAGS
-	if(this_opt) {
-		opt = simple_strtol( this_opt, NULL, 0 );
-		if (opt >= 0)
-			setup_use_tagged_queuing = !!opt;
-	}
-#endif
-#endif
-	return 1; 
-}
-
-__setup("mac53c9x=", mac_esp_setup);
-
-
-/*
- * ESP address 'detection'
- */
-
-unsigned long get_base(int chip_num)
-{
-	/*
-	 * using the chip_num and mac model, figure out where the
-	 * chips are mapped
-	 */
-
-	unsigned long io_base = 0x50f00000;
-	unsigned int second_offset = 0x402;
-	unsigned long scsi_loc = 0;
-
-	switch (macintosh_config->scsi_type) {
-
-	/* 950, 900, 700 */
-	case MAC_SCSI_QUADRA2:
-		scsi_loc =  io_base + 0xf000 + ((chip_num == 0) ? 0 : second_offset);
-		break;
-
-	/* av's */
-	case MAC_SCSI_QUADRA3:
-		scsi_loc = io_base + 0x18000 + ((chip_num == 0) ? 0 : second_offset);
-		break;
-
-	/* most quadra/centris models are like this */	
-	case MAC_SCSI_QUADRA:
-		scsi_loc = io_base + 0x10000;
-		break;
-
-	default:
-		printk("mac_esp: get_base: hit default!\n");
-		scsi_loc = io_base + 0x10000;
-		break;
-
-	} /* switch */
-
-	printk("mac_esp: io base at 0x%lx\n", scsi_loc);
-
-	return scsi_loc;
-}
-
-/*
- * Model dependent ESP setup
- */
-
-int mac_esp_detect(struct scsi_host_template * tpnt)
-{
-	int quick = 0;
-	int chipnum, chipspresent = 0;
-#if 0
-	unsigned long timeout;
-#endif
-
-	if (esp_initialized > 0)
-		return -ENODEV;
-
-	/* what do we have in this machine... */
-	if (MACHW_PRESENT(MAC_SCSI_96)) {
-		chipspresent ++;
-	}
-
-	if (MACHW_PRESENT(MAC_SCSI_96_2)) {
-		chipspresent ++;
-	}
-
-	/* number of ESPs present ? */
-	if (setup_num_esps >= 0) {
-	  if (chipspresent >= setup_num_esps)
-	    chipspresent = setup_num_esps;
-	  else
-	    printk("mac_esp_detect: num_hosts detected %d setup %d \n",
-		   chipspresent, setup_num_esps);
-	}
-
-	/* TODO: add disconnect / nosync flags */
-
-	/* setup variables */
-	tpnt->can_queue =
-	  (setup_can_queue > 0) ? setup_can_queue : 7;
-	tpnt->cmd_per_lun =
-	  (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1;
-	tpnt->sg_tablesize = 
-	  (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL;
-
-	if (setup_hostid >= 0)
-	  tpnt->this_id = setup_hostid;
-	else {
-	  /* use 7 as default */
-	  tpnt->this_id = 7;
-	}
-
-#ifdef SUPPORT_TAGS
-	if (setup_use_tagged_queuing < 0)
-		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
-#endif
-
-	for (chipnum = 0; chipnum < chipspresent; chipnum ++) {
-		struct NCR_ESP * esp;
-
-		esp = esp_allocate(tpnt, NULL, 0);
-		esp->eregs = (struct ESP_regs *) get_base(chipnum);
-
-		esp->dma_irq_p = &esp_dafb_dma_irq_p;
-		if (chipnum == 0) {
-
-			if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
-				/* most machines except those below :-) */
-				quick = 1;
-				esp->dma_irq_p = &esp_iosb_dma_irq_p;
-			} else if (macintosh_config->scsi_type == MAC_SCSI_QUADRA3) {
-				/* mostly av's */
-				quick = 0;
-			} else {
-				/* q950, 900, 700 */
-				quick = 1;
-				out_be32(0xf9800024, 0x1d1);
-				esp->dregs = (void *) 0xf9800024;
-			}
-
-		} else { /* chipnum */
-
-			quick = 1;
-			out_be32(0xf9800028, 0x1d1);
-			esp->dregs = (void *) 0xf9800028;
-
-		} /* chipnum == 0 */
-
-		/* use pio for command bytes; pio for message/data: TBI */
-		esp->do_pio_cmds = 1;
-
-		/* Set the command buffer */
-		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-		esp->esp_command_dvma = (__u32) cmd_buffer;
-
-		/* various functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = NULL;
-		esp->dma_init_write = NULL;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-
-		esp->dma_ports_p = &dma_ports_p;
-
-
-		/* Optional functions */
-		esp->dma_barrier = NULL;
-		esp->dma_drain = NULL;
-		esp->dma_invalidate = NULL;
-		esp->dma_irq_entry = NULL;
-		esp->dma_irq_exit = NULL;
-		esp->dma_led_on = NULL;
-		esp->dma_led_off = NULL;
-		esp->dma_poll = NULL;
-		esp->dma_reset = NULL;
-
-		/* SCSI chip speed */
-		/* below esp->cfreq = 40000000; */
-
-
-		if (quick) {
-			/* 'quick' means there's handshake glue logic like in the 5380 case */
-			esp->dma_setup = &dma_setup_quick;
-		} else {
-			esp->dma_setup = &dma_setup;
-		}
-
-		if (chipnum == 0) {
-
-			esp->irq = IRQ_MAC_SCSI;
-
-			request_irq(IRQ_MAC_SCSI, esp_intr, 0, "Mac ESP SCSI", esp->ehost);
-#if 0	/* conflicts with IOP ADB */
-			request_irq(IRQ_MAC_SCSIDRQ, fake_drq, 0, "Mac ESP DRQ", esp->ehost);
-#endif
-
-			if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
-				esp->cfreq = 16500000;
-			} else {
-				esp->cfreq = 25000000;
-			}
-
-
-		} else { /* chipnum == 1 */
-
-			esp->irq = IRQ_MAC_SCSIDRQ;
-#if 0	/* conflicts with IOP ADB */
-			request_irq(IRQ_MAC_SCSIDRQ, esp_intr, 0, "Mac ESP SCSI 2", esp->ehost);
-#endif
-
-			esp->cfreq = 25000000;
-
-		}
-
-		if (quick) {
-			printk("esp: using quick version\n");
-		}
-
-		printk("esp: addr at 0x%p\n", esp->eregs);
-
-		esp->scsi_id = 7;
-		esp->diff = 0;
-
-		esp_initialize(esp);
-
-	} /* for chipnum */
-
-	if (chipspresent)
-		printk("\nmac_esp: %d esp controllers found\n", chipspresent);
-
-	esp_initialized = chipspresent;
-
-	return chipspresent;
-}
-
-static int mac_esp_release(struct Scsi_Host *shost)
-{
-	if (shost->irq)
-		free_irq(shost->irq, NULL);
-	if (shost->io_port && shost->n_io_port)
-		release_region(shost->io_port, shost->n_io_port);
-	scsi_unregister(shost);
-	return 0;
-}
-
-/*
- * I've been wondering what this is supposed to do, for some time. Talking 
- * to Allen Briggs: These machines have an extra register someplace where the
- * DRQ pin of the ESP can be monitored. That isn't useful for determining 
- * anything else (such as reselect interrupt or other magic) though. 
- * Maybe make the semantics should be changed like 
- * if (esp->current_SC)
- *	... check DRQ flag ...
- * else 
- *	... disconnected, check pending VIA interrupt ...
- *
- * There's a problem with using the dabf flag or mac_irq_pending() here: both
- * seem to return 1 even though no interrupt is currently pending, resulting
- * in esp_exec_cmd() holding off the next command, and possibly infinite loops
- * in esp_intr(). 
- * Short term fix: just use esp_status & ESP_STAT_INTR here, as long as we
- * use simple PIO. The DRQ status will be important when implementing pseudo
- * DMA mode (set up ESP transfer count, return, do a batch of bytes in PIO or 
- * 'hardware handshake' mode upon DRQ).
- * If you plan on changing this (i.e. to save the esp_status register access in 
- * favor of a VIA register access or a shadow register for the IFR), make sure
- * to try a debug version of this first to monitor what registers would be a good
- * indicator of the ESP interrupt.
- */
-
-static int esp_dafb_dma_irq_p(struct NCR_ESP * esp)
-{
-	unsigned int ret;
-	int sreg = esp_read(esp->eregs->esp_status);
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n", 
-		readl(esp->dregs), mac_irq_pending(IRQ_MAC_SCSI));
-#endif
-
-	sreg &= ESP_STAT_INTR;
-
-	/*
-	 * maybe working; this is essentially what's used for iosb_dma_irq_p
-	 */
-	if (sreg)
-		return 1;
-	else
-		return 0;
-
-	/*
-	 * didn't work ...
-	 */
-#if 0
-	if (esp->current_SC)
-		ret = readl(esp->dregs) & 0x200;
-	else if (esp->disconnected_SC)
-		ret = 1; /* sreg ?? */
-	else
-		ret = mac_irq_pending(IRQ_MAC_SCSI);
-
-	return(ret);
-#endif
-
-}
-
-/*
- * See above: testing mac_irq_pending always returned 8 (SCSI IRQ) regardless 
- * of the actual ESP status.
- */
-
-static int esp_iosb_dma_irq_p(struct NCR_ESP * esp)
-{
-	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
-	int sreg = esp_read(esp->eregs->esp_status);
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
-		mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 
-		sreg, esp->current_SC, esp->disconnected_SC);
-#endif
-
-	sreg &= ESP_STAT_INTR;
-
-	if (sreg)
-		return (sreg);
-	else
-		return 0;
-}
-
-/*
- * This seems to be OK for PIO at least ... usually 0 after PIO.
- */
-
-static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count)
-{
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma bytes sent = %x\n", fifo_count);
-#endif
-
-	return fifo_count;
-}
-
-/*
- * dma_can_transfer is used to switch between DMA and PIO, if DMA (pseudo)
- * is ever implemented. Returning 0 here will use PIO.
- */
-
-static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd * sp)
-{
-	unsigned long sz = sp->SCp.this_residual;
-#if 0	/* no DMA yet; make conditional */
-	if (sz > 0x10000000) {
-		sz = 0x10000000;
-	}
-	printk("mac_esp: dma can transfer = 0lx%x\n", sz);
-#else
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: pio to transfer = %ld\n", sz);
-#endif
-
-	sz = 0;
-#endif
-	return sz;
-}
-
-/*
- * Not yet ...
- */
-
-static void dma_dump_state(struct NCR_ESP * esp)
-{
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_dump_state: called\n");
-#endif
-#if 0
-	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
-		esp->esp_id, ((struct mac_dma_registers *)
-		(esp->dregs))->cond_reg));
-#endif
-}
-
-/*
- * DMA setup: should be used to set up the ESP transfer count for pseudo
- * DMA transfers; need a DRQ transfer function to do the actual transfer
- */
-
-static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length)
-{
-	printk("mac_esp: dma_init_read\n");
-}
-
-
-static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length)
-{
-	printk("mac_esp: dma_init_write\n");
-}
-
-
-static void dma_ints_off(struct NCR_ESP * esp)
-{
-	disable_irq(esp->irq);
-}
-
-
-static void dma_ints_on(struct NCR_ESP * esp)
-{
-	enable_irq(esp->irq);
-}
-
-/*
- * generic dma_irq_p(), unused
- */
-
-static int dma_irq_p(struct NCR_ESP * esp)
-{
-	int i = esp_read(esp->eregs->esp_status);
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_irq_p status %d\n", i);
-#endif
-
-	return (i & ESP_STAT_INTR);
-}
-
-static int dma_irq_p_quick(struct NCR_ESP * esp)
-{
-	/*
-	 * Copied from iosb_dma_irq_p()
-	 */
-	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
-	int sreg = esp_read(esp->eregs->esp_status);
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
-		mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 
-		sreg, esp->current_SC, esp->disconnected_SC);
-#endif
-
-	sreg &= ESP_STAT_INTR;
-
-	if (sreg)
-		return (sreg);
-	else
-		return 0;
-
-}
-
-static void dma_led_off(struct NCR_ESP * esp)
-{
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_led_off: called\n");
-#endif
-}
-
-
-static void dma_led_on(struct NCR_ESP * esp)
-{
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_led_on: called\n");
-#endif
-}
-
-
-static int dma_ports_p(struct NCR_ESP * esp)
-{
-	return 0;
-}
-
-
-static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write)
-{
-
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_setup\n");
-#endif
-
-	if (write) {
-		dma_init_read(esp, (char *) addr, count);
-	} else {
-		dma_init_write(esp, (char *) addr, count);
-	}
-}
-
-
-static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write)
-{
-#ifdef DEBUG_MAC_ESP
-	printk("mac_esp: dma_setup_quick\n");
-#endif
-}
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "mac_esp",
-	.name			= "Mac 53C9x SCSI",
-	.detect			= mac_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= mac_esp_release,
-	.info			= esp_info,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
deleted file mode 100644
index d693d0f..0000000
--- a/drivers/scsi/mca_53c9x.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* mca_53c9x.c: Driver for the SCSI adapter found on NCR 35xx
- *  (and maybe some other) Microchannel machines
- *
- * Code taken mostly from Cyberstorm SCSI drivers
- *   Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
- *
- * The CyberStorm SCSI driver (and this driver) is based on David S. Miller's
- *   ESP driver  * for the Sparc computers. 
- * 
- * Special thanks to Ken Stewart at Symbios (LSI) for helping with info on
- *  the 86C01.  I was on the brink of going ga-ga...
- *
- * Also thanks to Jesper Skov for helping me with info on how the Amiga
- *  does things...
- */
-
-/*
- * This is currently only set up to use one 53c9x card at a time; it could be 
- *  changed fairly easily to detect/use more than one, but I'm not too sure how
- *  many cards that use the 53c9x on MCA systems there are (if, in fact, there
- *  are cards that use them, other than the one built into some NCR systems)...
- *  If anyone requests this, I'll throw it in, otherwise it's not worth the
- *  effort.
- */
-
-/*
- * Info on the 86C01 MCA interface chip at the bottom, if you care enough to
- *  look.
- */
-
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mca.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/mca-legacy.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <asm/dma.h>
-#include <asm/irq.h>
-#include <asm/mca_dma.h>
-#include <asm/pgtable.h>
-
-/*
- * From ibmmca.c (IBM scsi controller card driver) -- used for turning PS2 disk
- *  activity LED on and off
- */
-
-#define PS2_SYS_CTR	0x92
-
-/* Ports the ncr's 53c94 can be put at; indexed by pos register value */
-
-#define MCA_53C9X_IO_PORTS {                             \
-                         0x0000, 0x0240, 0x0340, 0x0400, \
-	                 0x0420, 0x3240, 0x8240, 0xA240, \
-	                }
-			
-/*
- * Supposedly there were some cards put together with the 'c9x and 86c01.  If
- *   they have different ID's from the ones on the 3500 series machines, 
- *   you can add them here and hopefully things will work out.
- */
-			
-#define MCA_53C9X_IDS {          \
-                         0x7F4C, \
-			 0x0000, \
-                        }
-
-static int  dma_bytes_sent(struct NCR_ESP *, int);
-static int  dma_can_transfer(struct NCR_ESP *, Scsi_Cmnd *);
-static void dma_dump_state(struct NCR_ESP *);
-static void dma_init_read(struct NCR_ESP *, __u32, int);
-static void dma_init_write(struct NCR_ESP *, __u32, int);
-static void dma_ints_off(struct NCR_ESP *);
-static void dma_ints_on(struct NCR_ESP *);
-static int  dma_irq_p(struct NCR_ESP *);
-static int  dma_ports_p(struct NCR_ESP *);
-static void dma_setup(struct NCR_ESP *, __u32, int, int);
-static void dma_led_on(struct NCR_ESP *);
-static void dma_led_off(struct NCR_ESP *);
-
-/* This is where all commands are put before they are trasfered to the 
- *  53c9x via PIO.
- */
-
-static volatile unsigned char cmd_buffer[16];
-
-/*
- * We keep the structure that is used to access the registers on the 53c9x
- *  here.
- */
-
-static struct ESP_regs eregs;
-
-/***************************************************************** Detection */
-static int mca_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	static int io_port_by_pos[] = MCA_53C9X_IO_PORTS;
-	int mca_53c9x_ids[] = MCA_53C9X_IDS;
-	int *id_to_check = mca_53c9x_ids;
-	int slot;
-	int pos[3];
-	unsigned int tmp_io_addr;
-	unsigned char tmp_byte;
-
-
-	if (!MCA_bus)
-		return 0;
-
-	while (*id_to_check) { 
-		if ((slot = mca_find_adapter(*id_to_check, 0)) !=
-		  MCA_NOTFOUND) 
-		{
-			esp = esp_allocate(tpnt, NULL, 0);
-
-			pos[0] = mca_read_stored_pos(slot, 2);
-			pos[1] = mca_read_stored_pos(slot, 3);
-			pos[2] = mca_read_stored_pos(slot, 4);
-
-			esp->eregs = &eregs;
-
-			/*
-			 * IO port base is given in the first (non-ID) pos
-			 *  register, like so:
-			 *
-			 *  Bits 3  2  1       IO base
-			 * ----------------------------
-			 *       0  0  0       <disabled>
-			 *       0  0  1       0x0240
-			 *       0  1  0       0x0340
-			 *       0  1  1       0x0400
-			 *       1  0  0       0x0420
-			 *       1  0  1       0x3240
-			 *       1  1  0       0x8240
-			 *       1  1  1       0xA240
-			 */
-
-			tmp_io_addr =
-			  io_port_by_pos[(pos[0] & 0x0E) >> 1];
-
-			esp->eregs->io_addr = tmp_io_addr + 0x10;
-
-      			if (esp->eregs->io_addr == 0x0000) { 
-        			printk("Adapter is disabled.\n");
-				break;
-			}
-
-			/*
-			 * IRQ is specified in bits 4 and 5:
-			 *
-			 *  Bits  4  5        IRQ
-			 * -----------------------
-			 *        0  0         3
-			 *        0  1         5
-			 *        1  0         7
-			 *        1  1         9
-			 */
-
-      			esp->irq = ((pos[0] & 0x30) >> 3) + 3;
-
-			/*
-			 * DMA channel is in the low 3 bits of the second
-			 *  POS register
-			 */
-
-			esp->dma = pos[1] & 7;
-			esp->slot = slot;
-
-			if (request_irq(esp->irq, esp_intr, 0,
-			 "NCR 53c9x SCSI", esp->ehost))
-			{
-				printk("Unable to request IRQ %d.\n", esp->irq);
-				esp_deallocate(esp);
-				scsi_unregister(esp->ehost);
-				return 0;
-			}
-
- 			if (request_dma(esp->dma, "NCR 53c9x SCSI")) {
-				printk("Unable to request DMA channel %d.\n",
-				 esp->dma);
-				free_irq(esp->irq, esp_intr);
-				esp_deallocate(esp);
-				scsi_unregister(esp->ehost);
-				return 0;
-			}
-
-			request_region(tmp_io_addr, 32, "NCR 53c9x SCSI");
-
-			/*
-			 * 86C01 handles DMA, IO mode, from address
-			 *  (base + 0x0a)
-			 */
-
-			mca_disable_dma(esp->dma);
-			mca_set_dma_io(esp->dma, tmp_io_addr + 0x0a);
-			mca_enable_dma(esp->dma);
- 
-			/* Tell the 86C01 to give us interrupts */
-
-			tmp_byte = inb(tmp_io_addr + 0x02) | 0x40;
-			outb(tmp_byte, tmp_io_addr + 0x02); 
-
-			/*
-			 * Scsi ID -- general purpose register, hi
-			 *  2 bits; add 4 to this number to get the
-			 *  ID
-			 */
-
-			esp->scsi_id = ((pos[2] & 0xC0) >> 6) + 4;
-
-			/* Do command transfer with programmed I/O */
-
-			esp->do_pio_cmds = 1;
-
-			/* Required functions */
-
-			esp->dma_bytes_sent = &dma_bytes_sent;
-			esp->dma_can_transfer = &dma_can_transfer;
-			esp->dma_dump_state = &dma_dump_state;
-			esp->dma_init_read = &dma_init_read;
-			esp->dma_init_write = &dma_init_write;
-			esp->dma_ints_off = &dma_ints_off;
-			esp->dma_ints_on = &dma_ints_on;
-			esp->dma_irq_p = &dma_irq_p;
-			esp->dma_ports_p = &dma_ports_p;
-			esp->dma_setup = &dma_setup;
-
-			/* Optional functions */
-
-			esp->dma_barrier = NULL;
-			esp->dma_drain = NULL;
-			esp->dma_invalidate = NULL;
-			esp->dma_irq_entry = NULL;
-			esp->dma_irq_exit = NULL;
-			esp->dma_led_on = dma_led_on;
-			esp->dma_led_off = dma_led_off;
-			esp->dma_poll = NULL;
-			esp->dma_reset = NULL;
-
-			/* Set the command buffer */
-
-			esp->esp_command = (volatile unsigned char*)
-			  cmd_buffer;
-	 		esp->esp_command_dvma = isa_virt_to_bus(cmd_buffer);
-
-			/* SCSI chip speed */
-
-			esp->cfreq = 25000000;
-
-			/* Differential SCSI? I think not. */
-
-			esp->diff = 0;
-
-			esp_initialize(esp);
-
-      			printk(" Adapter found in slot %2d: io port 0x%x "
-			  "irq %d dma channel %d\n", slot + 1, tmp_io_addr,
-			   esp->irq, esp->dma);
-
-			mca_set_adapter_name(slot, "NCR 53C9X SCSI Adapter");
-			mca_mark_as_used(slot);
-
-			break;
-		}
-    
-		id_to_check++;
-	}
-
-	return esps_in_use;
-}
-
-
-/******************************************************************* Release */
-
-static int mca_esp_release(struct Scsi_Host *host)
-{
-	struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata;
-	unsigned char tmp_byte;
-
-	esp_deallocate(esp);
-	/*
-	 * Tell the 86C01 to stop sending interrupts
-	 */
-
-	tmp_byte = inb(esp->eregs->io_addr - 0x0E);
-	tmp_byte &= ~0x40;
-	outb(tmp_byte, esp->eregs->io_addr - 0x0E);
-
-	free_irq(esp->irq, esp_intr);
-	free_dma(esp->dma);
-
-	mca_mark_as_unused(esp->slot);
-
-	return 0;
-}
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Ask the 53c9x.  It knows. */
-
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	/* 
-	 * The MCA dma channels can only do up to 128K bytes at a time.
-         *  (16 bit mode)
-	 */
-
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > 0x20000)
-		sz = 0x20000;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-	/*
-	 * Doesn't quite match up to the other drivers, but we do what we
-	 *  can.
-	 */
-
-	ESPLOG(("esp%d: dma channel <%d>\n", esp->esp_id, esp->dma));
-	ESPLOG(("bytes left to dma: %d\n", mca_get_dma_residue(esp->dma)));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	unsigned long flags;
-
-
-	save_flags(flags);
-	cli();
-
-	mca_disable_dma(esp->dma);
-	mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_16 |
-	  MCA_DMA_MODE_IO);
-	mca_set_dma_addr(esp->dma, addr);
-	mca_set_dma_count(esp->dma, length / 2); /* !!! */
-	mca_enable_dma(esp->dma);
-
-	restore_flags(flags);
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
-{
-	unsigned long flags;
-
-
-	save_flags(flags);
-	cli();
-
-	mca_disable_dma(esp->dma);
-	mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_WRITE |
-	  MCA_DMA_MODE_16 | MCA_DMA_MODE_IO);
-	mca_set_dma_addr(esp->dma, addr);
-	mca_set_dma_count(esp->dma, length / 2); /* !!! */
-	mca_enable_dma(esp->dma);
-
-	restore_flags(flags);
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	/*
-	 * Tell the 'C01 to shut up.  All interrupts are routed through it.
-	 */
-
-	outb(inb(esp->eregs->io_addr - 0x0E) & ~0x40,
-	 esp->eregs->io_addr - 0x0E);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	/*
-	 * Ok.  You can speak again.
-	 */
-
-	outb(inb(esp->eregs->io_addr - 0x0E) | 0x40,
-	 esp->eregs->io_addr - 0x0E);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	/*
-	 * DaveM says that this should return a "yes" if there is an interrupt
-	 *  or a DMA error occurred.  I copied the Amiga driver's semantics,
-	 *  though, because it seems to work and we can't really tell if
-	 *  a DMA error happened.  This gives the "yes" if the scsi chip
-	 *  is sending an interrupt and no DMA activity is taking place
-	 */
-
-	return (!(inb(esp->eregs->io_addr - 0x04) & 1) &&
-	 !(inb(esp->eregs->io_addr - 0x04) & 2) ); 
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	/*
-	 * Check to see if interrupts are enabled on the 'C01 (in case abort
-	 *  is entered multiple times, so we only do the abort once)
-	 */
-
-	return (inb(esp->eregs->io_addr - 0x0E) & 0x40) ? 1:0;
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	if(write){
-		dma_init_write(esp, addr, count);
-	} else {
-		dma_init_read(esp, addr, count);
-	}
-}
-
-/*
- * These will not play nicely with other disk controllers that try to use the
- *  disk active LED... but what can you do?  Don't answer that.
- *
- * Stolen shamelessly from ibmmca.c -- IBM Microchannel SCSI adapter driver
- *
- */
-
-static void dma_led_on(struct NCR_ESP *esp)
-{
-	outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR);
-}
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-	outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR);
-}
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "mca_53c9x",
-	.name			= "NCR 53c9x SCSI",
-	.detect			= mca_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= mca_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.unchecked_isa_dma	= 1,
-	.use_clustering		= DISABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-/*
- * OK, here's the goods I promised.  The NCR 86C01 is an MCA interface chip 
- *  that handles enabling/diabling IRQ, dma interfacing, IO port selection
- *  and other fun stuff.  It takes up 16 addresses, and the chip it is
- *  connnected to gets the following 16.  Registers are as follows:
- *
- * Offsets 0-1 : Card ID
- *
- * Offset    2 : Mode enable register --
- *                Bit    7 : Data Word width (1 = 16, 0 = 8)
- *		  Bit    6 : IRQ enable (1 = enabled)
- *                Bits 5,4 : IRQ select
- *                              0  0 : IRQ 3
- *			        0  1 : IRQ 5
- * 				1  0 : IRQ 7
- *  				1  1 : IRQ 9
- *                Bits 3-1 : Base Address
- *                           0  0  0 : <disabled>
- * 			     0  0  1 : 0x0240
- *    			     0  1  0 : 0x0340
- *     			     0  1  1 : 0x0400
- * 			     1  0  0 : 0x0420
- * 			     1  0  1 : 0x3240
- * 			     1  1  0 : 0x8240
- * 			     1  1  1 : 0xA240
- *		  Bit    0 : Card enable (1 = enabled)
- *
- * Offset    3 : DMA control register --
- *                Bit    7 : DMA enable (1 = enabled)
- *                Bits 6,5 : Preemt Count Select (transfers to complete after
- *                            'C01 has been preempted on MCA bus)
- *                              0  0 : 0
- *                              0  1 : 1
- *                              1  0 : 3
- *                              1  1 : 7
- *  (all these wacky numbers; I'm sure there's a reason somewhere)
- *                Bit    4 : Fairness enable (1 = fair bus priority)
- *                Bits 3-0 : Arbitration level (0-15 consecutive)
- * 
- * Offset    4 : General purpose register
- *                Bits 7-3 : User definable (here, 7,6 are SCSI ID)
- *                Bits 2-0 : reserved
- *
- * Offset   10 : DMA decode register (used for IO based DMA; also can do
- *                PIO through this port)
- *
- * Offset   12 : Status
- *                Bits 7-2 : reserved
- *                Bit    1 : DMA pending (1 = pending)
- *                Bit    0 : IRQ pending (0 = pending)
- *
- * Exciting, huh?  
- *
- */                
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
deleted file mode 100644
index 8e5eadb..0000000
--- a/drivers/scsi/oktagon_esp.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Oktagon_esp.c -- Driver for bsc Oktagon
- *
- * Written by Carsten Pluntke 1998
- *
- * Based on cyber_esp.c
- */
-
-
-#if defined(CONFIG_AMIGA) || defined(CONFIG_APUS)
-#define USE_BOTTOM_HALF
-#endif
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/reboot.h>
-#include <asm/system.h>
-#include <asm/ptrace.h>
-#include <asm/pgtable.h>
-
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#ifdef USE_BOTTOM_HALF
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#endif
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define OKTAGON_ESP_ADDR 0x03000
-#define OKTAGON_DMA_ADDR 0x01000
-
-
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static void dma_led_off(struct NCR_ESP *esp);
-static void dma_led_on(struct NCR_ESP *esp);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-
-static void dma_irq_exit(struct NCR_ESP *esp);
-static void dma_invalidate(struct NCR_ESP *esp);
-
-static void dma_mmu_get_scsi_one(struct NCR_ESP *,Scsi_Cmnd *);
-static void dma_mmu_get_scsi_sgl(struct NCR_ESP *,Scsi_Cmnd *);
-static void dma_mmu_release_scsi_one(struct NCR_ESP *,Scsi_Cmnd *);
-static void dma_mmu_release_scsi_sgl(struct NCR_ESP *,Scsi_Cmnd *);
-static void dma_advance_sg(Scsi_Cmnd *);
-static int  oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x);
-
-#ifdef USE_BOTTOM_HALF
-static void dma_commit(struct work_struct *unused);
-
-long oktag_to_io(long *paddr, long *addr, long len);
-long oktag_from_io(long *addr, long *paddr, long len);
-
-static DECLARE_WORK(tq_fake_dma, dma_commit);
-
-#define DMA_MAXTRANSFER 0x8000
-
-#else
-
-/*
- * No bottom half. Use transfer directly from IRQ. Find a narrow path
- * between too much IRQ overhead and clogging the IRQ for too long.
- */
-
-#define DMA_MAXTRANSFER 0x1000
-
-#endif
-
-static struct notifier_block oktagon_notifier = { 
-	oktagon_notify_reboot,
-	NULL,
-	0
-};
-
-static long *paddress;
-static long *address;
-static long len;
-static long dma_on;
-static int direction;
-static struct NCR_ESP *current_esp;
-
-
-static volatile unsigned char cmd_buffer[16];
-				/* This is where all commands are put
-				 * before they are trasfered to the ESP chip
-				 * via PIO.
-				 */
-
-/***************************************************************** Detection */
-int oktagon_esp_detect(struct scsi_host_template *tpnt)
-{
-	struct NCR_ESP *esp;
-	struct zorro_dev *z = NULL;
-	unsigned long address;
-	struct ESP_regs *eregs;
-
-	while ((z = zorro_find_device(ZORRO_PROD_BSC_OKTAGON_2008, z))) {
-	    unsigned long board = z->resource.start;
-	    if (request_mem_region(board+OKTAGON_ESP_ADDR,
-				   sizeof(struct ESP_regs), "NCR53C9x")) {
-		/*
-		 * It is a SCSI controller.
-		 * Hardwire Host adapter to SCSI ID 7
-		 */
-		
-		address = (unsigned long)ZTWO_VADDR(board);
-		eregs = (struct ESP_regs *)(address + OKTAGON_ESP_ADDR);
-
-		/* This line was 5 lines lower */
-		esp = esp_allocate(tpnt, (void *)board + OKTAGON_ESP_ADDR, 0);
-
-		/* we have to shift the registers only one bit for oktagon */
-		esp->shift = 1;
-
-		esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
-		udelay(5);
-		if (esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7))
-			return 0; /* Bail out if address did not hold data */
-
-		/* Do command transfer with programmed I/O */
-		esp->do_pio_cmds = 1;
-
-		/* Required functions */
-		esp->dma_bytes_sent = &dma_bytes_sent;
-		esp->dma_can_transfer = &dma_can_transfer;
-		esp->dma_dump_state = &dma_dump_state;
-		esp->dma_init_read = &dma_init_read;
-		esp->dma_init_write = &dma_init_write;
-		esp->dma_ints_off = &dma_ints_off;
-		esp->dma_ints_on = &dma_ints_on;
-		esp->dma_irq_p = &dma_irq_p;
-		esp->dma_ports_p = &dma_ports_p;
-		esp->dma_setup = &dma_setup;
-
-		/* Optional functions */
-		esp->dma_barrier = 0;
-		esp->dma_drain = 0;
-		esp->dma_invalidate = &dma_invalidate;
-		esp->dma_irq_entry = 0;
-		esp->dma_irq_exit = &dma_irq_exit;
-		esp->dma_led_on = &dma_led_on;
-		esp->dma_led_off = &dma_led_off;
-		esp->dma_poll = 0;
-		esp->dma_reset = 0;
-
-		esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
-		esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
-		esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
-		esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
-		esp->dma_advance_sg = &dma_advance_sg;
-
-		/* SCSI chip speed */
-		/* Looking at the quartz of the SCSI board... */
-		esp->cfreq = 25000000;
-
-		/* The DMA registers on the CyberStorm are mapped
-		 * relative to the device (i.e. in the same Zorro
-		 * I/O block).
-		 */
-		esp->dregs = (void *)(address + OKTAGON_DMA_ADDR);
-
-		paddress = (long *) esp->dregs;
-
-		/* ESP register base */
-		esp->eregs = eregs;
-		
-		/* Set the command buffer */
-		esp->esp_command = (volatile unsigned char*) cmd_buffer;
-
-		/* Yes, the virtual address. See below. */
-		esp->esp_command_dvma = (__u32) cmd_buffer;
-
-		esp->irq = IRQ_AMIGA_PORTS;
-		request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
-			    "BSC Oktagon SCSI", esp->ehost);
-
-		/* Figure out our scsi ID on the bus */
-		esp->scsi_id = 7;
-		
-		/* We don't have a differential SCSI-bus. */
-		esp->diff = 0;
-
-		esp_initialize(esp);
-
-		printk("ESP_Oktagon Driver 1.1"
-#ifdef USE_BOTTOM_HALF
-		       " [BOTTOM_HALF]"
-#else
-		       " [IRQ]"
-#endif
-		       " registered.\n");
-		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
-		esps_running = esps_in_use;
-		current_esp = esp;
-		register_reboot_notifier(&oktagon_notifier);
-		return esps_in_use;
-	    }
-	}
-	return 0;
-}
-
-
-/*
- * On certain configurations the SCSI equipment gets confused on reboot,
- * so we have to reset it then.
- */
-
-static int
-oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
-{
-  struct NCR_ESP *esp;
-  
-  if((code == SYS_DOWN || code == SYS_HALT) && (esp = current_esp))
-   {
-    esp_bootup_reset(esp,esp->eregs);
-    udelay(500); /* Settle time. Maybe unnecessary. */
-   }
-  return NOTIFY_DONE;
-}
-    
-
-	
-#ifdef USE_BOTTOM_HALF
-
-
-/*
- * The bsc Oktagon controller has no real DMA, so we have to do the 'DMA
- * transfer' in the interrupt (Yikes!) or use a bottom half to not to clutter
- * IRQ's for longer-than-good.
- *
- * FIXME
- * BIG PROBLEM: 'len' is usually the buffer length, not the expected length
- * of the data. So DMA may finish prematurely, further reads lead to
- * 'machine check' on APUS systems (don't know about m68k systems, AmigaOS
- * deliberately ignores the bus faults) and a normal copy-loop can't
- * be exited prematurely just at the right moment by the dma_invalidate IRQ.
- * So do it the hard way, write an own copier in assembler and
- * catch the exception.
- *                                     -- Carsten
- */
- 
- 
-static void dma_commit(struct work_struct *unused)
-{
-    long wait,len2,pos;
-    struct NCR_ESP *esp;
-
-    ESPDATA(("Transfer: %ld bytes, Address 0x%08lX, Direction: %d\n",
-         len,(long) address,direction));
-    dma_ints_off(current_esp);
-
-    pos = 0;
-    wait = 1;
-    if(direction) /* write? (memory to device) */
-     {
-      while(len > 0)
-       {
-        len2 = oktag_to_io(paddress, address+pos, len);
-	if(!len2)
-	 {
-	  if(wait > 1000)
-	   {
-	    printk("Expedited DMA exit (writing) %ld\n",len);
-	    break;
-	   }
-	  mdelay(wait);
-	  wait *= 2;
-	 }
-	pos += len2;
-	len -= len2*sizeof(long);
-       }
-     } else {
-      while(len > 0)
-       {
-        len2 = oktag_from_io(address+pos, paddress, len);
-	if(!len2)
-	 {
-	  if(wait > 1000)
-	   {
-	    printk("Expedited DMA exit (reading) %ld\n",len);
-	    break;
-	   }
-	  mdelay(wait);
-	  wait *= 2;
-	 }
-	pos += len2;
-	len -= len2*sizeof(long);
-       }
-     }
-
-    /* to make esp->shift work */
-    esp=current_esp;
-
-#if 0
-    len2 = (esp_read(current_esp->eregs->esp_tclow) & 0xff) |
-           ((esp_read(current_esp->eregs->esp_tcmed) & 0xff) << 8);
-
-    /*
-     * Uh uh. If you see this, len and transfer count registers were out of
-     * sync. That means really serious trouble.
-     */
-
-    if(len2)
-      printk("Eeeek!! Transfer count still %ld!\n",len2);
-#endif
-
-    /*
-     * Normally we just need to exit and wait for the interrupt to come.
-     * But at least one device (my Microtek ScanMaker 630) regularly mis-
-     * calculates the bytes it should send which is really ugly because
-     * it locks up the SCSI bus if not accounted for.
-     */
-
-    if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
-     {
-      long len = 100;
-      long trash[10];
-
-      /*
-       * Interrupt bit was not set. Either the device is just plain lazy
-       * so we give it a 10 ms chance or...
-       */
-      while(len-- && (!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR)))
-        udelay(100);
-
-
-      if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
-       {
-        /*
-	 * So we think that the transfer count is out of sync. Since we
-	 * have all we want we are happy and can ditch the trash.
-	 */
-	 
-        len = DMA_MAXTRANSFER;
-
-        while(len-- && (!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR)))
-          oktag_from_io(trash,paddress,2);
-
-        if(!(esp_read(current_esp->eregs->esp_status) & ESP_STAT_INTR))
-         {
-          /*
-           * Things really have gone wrong. If we leave the system in that
-           * state, the SCSI bus is locked forever. I hope that this will
-           * turn the system in a more or less running state.
-           */
-          printk("Device is bolixed, trying bus reset...\n");
-	  esp_bootup_reset(current_esp,current_esp->eregs);
-         }
-       }
-     }
-
-    ESPDATA(("Transfer_finale: do_data_finale should come\n"));
-
-    len = 0;
-    dma_on = 0;
-    dma_ints_on(current_esp);
-}
-
-#endif
-
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
-{
-	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
-	 * the number of bytes sent (to the ESP chip) equals the number
-	 * of bytes in the FIFO - there is no buffering in the DMA controller.
-	 * XXXX Do I read this right? It is from host to ESP, right?
-	 */
-	return fifo_count;
-}
-
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-	unsigned long sz = sp->SCp.this_residual;
-	if(sz > DMA_MAXTRANSFER)
-		sz = DMA_MAXTRANSFER;
-	return sz;
-}
-
-static void dma_dump_state(struct NCR_ESP *esp)
-{
-}
-
-/*
- * What the f$@& is this?
- *
- * Some SCSI devices (like my Microtek ScanMaker 630 scanner) want to transfer
- * more data than requested. How much? Dunno. So ditch the bogus data into
- * the sink, hoping the device will advance to the next phase sooner or later.
- *
- *                         -- Carsten
- */
-
-static long oktag_eva_buffer[16]; /* The data sink */
-
-static void oktag_check_dma(void)
-{
-  struct NCR_ESP *esp;
-
-  esp=current_esp;
-  if(!len)
-   {
-    address = oktag_eva_buffer;
-    len = 2;
-    /* esp_do_data sets them to zero like len */
-    esp_write(current_esp->eregs->esp_tclow,2);
-    esp_write(current_esp->eregs->esp_tcmed,0);
-   }
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
-{
-	/* Zorro is noncached, everything else done using processor. */
-	/* cache_clear(addr, length); */
-	
-	if(dma_on)
-	  panic("dma_init_read while dma process is initialized/running!\n");
-	direction = 0;
-	address = (long *) vaddress;
-	current_esp = esp;
-	len = length;
-	oktag_check_dma();
-        dma_on = 1;
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
-{
-	/* cache_push(addr, length); */
-
-	if(dma_on)
-	  panic("dma_init_write while dma process is initialized/running!\n");
-	direction = 1;
-	address = (long *) vaddress;
-	current_esp = esp;
-	len = length;
-	oktag_check_dma();
-	dma_on = 1;
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	disable_irq(esp->irq);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	enable_irq(esp->irq);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	/* It's important to check the DMA IRQ bit in the correct way! */
-	return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
-}
-
-static void dma_led_off(struct NCR_ESP *esp)
-{
-}
-
-static void dma_led_on(struct NCR_ESP *esp)
-{
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return ((amiga_custom.intenar) & IF_PORTS);
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-	/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-	 * so when (write) is true, it actually means READ!
-	 */
-	if(write){
-		dma_init_read(esp, addr, count);
-	} else {
-		dma_init_write(esp, addr, count);
-	}
-}
-
-/*
- * IRQ entry when DMA transfer is ready to be started
- */
-
-static void dma_irq_exit(struct NCR_ESP *esp)
-{
-#ifdef USE_BOTTOM_HALF
-	if(dma_on)
-	 {
-	  schedule_work(&tq_fake_dma);
-	 }
-#else
-	while(len && !dma_irq_p(esp))
-	 {
-	  if(direction)
-	    *paddress = *address++;
-	   else
-	    *address++ = *paddress;
-	  len -= (sizeof(long));
-	 }
-	len = 0;
-        dma_on = 0;
-#endif
-}
-
-/*
- * IRQ entry when DMA has just finished
- */
-
-static void dma_invalidate(struct NCR_ESP *esp)
-{
-}
-
-/*
- * Since the processor does the data transfer we have to use the custom
- * mmu interface to pass the virtual address, not the physical.
- */
-
-void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-        sp->SCp.ptr =
-                sp->request_buffer;
-}
-
-void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-        sp->SCp.ptr = sg_virt(sp->SCp.buffer);
-}
-
-void dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-}
-
-void dma_mmu_release_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-}
-
-void dma_advance_sg(Scsi_Cmnd *sp)
-{
-	sp->SCp.ptr = sg_virt(sp->SCp.buffer);
-}
-
-
-#define HOSTS_C
-
-int oktagon_esp_release(struct Scsi_Host *instance)
-{
-#ifdef MODULE
-	unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
-	esp_release();
-	release_mem_region(address, sizeof(struct ESP_regs));
-	free_irq(IRQ_AMIGA_PORTS, esp_intr);
-	unregister_reboot_notifier(&oktagon_notifier);
-#endif
-	return 1;
-}
-
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp-oktagon",
-	.proc_info		= &esp_proc_info,
-	.name			= "BSC Oktagon SCSI",
-	.detect			= oktagon_esp_detect,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.release		= oktagon_esp_release,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= ENABLE_CLUSTERING
-};
-
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/oktagon_io.S b/drivers/scsi/oktagon_io.S
deleted file mode 100644
index 8a7340b..0000000
--- a/drivers/scsi/oktagon_io.S
+++ /dev/null
@@ -1,194 +0,0 @@
-/* -*- mode: asm -*-
- * Due to problems while transferring data I've put these routines as assembly
- * code.
- * Since I'm no PPC assembler guru, the code is just the assembler version of
-
-int oktag_to_io(long *paddr,long *addr,long len)
-{
-  long *addr2 = addr;
-  for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
-    *paddr = *addr2++;
-  return addr2 - addr;
-}
-
-int oktag_from_io(long *addr,long *paddr,long len)
-{
-  long *addr2 = addr;
-  for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
-    *addr2++ = *paddr;
-  return addr2 - addr;
-}
-
- * assembled using gcc -O2 -S, with two exception catch points where data
- * is moved to/from the IO register.
- */
-
-
-#ifdef CONFIG_APUS
-
-	.file	"oktagon_io.c"
-
-gcc2_compiled.:
-/*
-	.section ".text"
-*/
-	.align 2
-	.globl oktag_to_io
-	.type	 oktag_to_io,@function
-oktag_to_io:
-	addi 5,5,3
-	srwi 5,5,2
-	cmpwi 1,5,0
-	mr 9,3
-	mr 3,4
-	addi 5,5,-1
-	bc 12,6,.L3
-.L5:
-	cmpwi 1,5,0
-	lwz 0,0(3)
-	addi 3,3,4
-	addi 5,5,-1
-exp1:	stw 0,0(9)
-	bc 4,6,.L5
-.L3:
-ret1:	subf 3,4,3
-	srawi 3,3,2
-	blr
-.Lfe1:
-	.size	 oktag_to_io,.Lfe1-oktag_to_io
-	.align 2
-	.globl oktag_from_io
-	.type	 oktag_from_io,@function
-oktag_from_io:
-	addi 5,5,3
-	srwi 5,5,2
-	cmpwi 1,5,0
-	mr 9,3
-	addi 5,5,-1
-	bc 12,6,.L9
-.L11:
-	cmpwi 1,5,0
-exp2:	lwz 0,0(4)
-	addi 5,5,-1
-	stw 0,0(3)
-	addi 3,3,4
-	bc 4,6,.L11
-.L9:
-ret2:	subf 3,9,3
-	srawi 3,3,2
-	blr
-.Lfe2:
-	.size	 oktag_from_io,.Lfe2-oktag_from_io
-	.ident	"GCC: (GNU) egcs-2.90.29 980515 (egcs-1.0.3 release)"
-
-/*
- * Exception table.
- * Second longword shows where to jump when an exception at the addr the first
- * longword is pointing to is caught.
- */
-
-.section __ex_table,"a"
-	.align	2
-oktagon_except:
-	.long	exp1,ret1
-	.long	exp2,ret2
-
-#else
-
-/*
-The code which follows is for 680x0 based assembler and is meant for
-Linux/m68k. It was created by cross compiling the code using the
-instructions given above. I then added the four labels used in the
-exception handler table at the bottom of this file.
-- Kevin <kcozens@interlog.com>
-*/
-
-#ifdef CONFIG_AMIGA
-
-	.file	"oktagon_io.c"
-	.version	"01.01"
-gcc2_compiled.:
-.text
-	.align 	2
-.globl oktag_to_io
-	.type	 oktag_to_io,@function
-oktag_to_io:
-	link.w %a6,#0
-	move.l %d2,-(%sp)
-	move.l 8(%a6),%a1
-	move.l 12(%a6),%d1
-	move.l %d1,%a0
-	move.l 16(%a6),%d0
-	addq.l #3,%d0
-	lsr.l #2,%d0
-	subq.l #1,%d0
-	moveq.l #-1,%d2
-	cmp.l %d0,%d2
-	jbeq .L3
-.L5:
-exp1:
-	move.l (%a0)+,(%a1)
-	dbra %d0,.L5
-	clr.w %d0
-	subq.l #1,%d0
-	jbcc .L5
-.L3:
-ret1:
-	move.l %a0,%d0
-	sub.l %d1,%d0
-	asr.l #2,%d0
-	move.l -4(%a6),%d2
-	unlk %a6
-	rts
-
-.Lfe1:
-	.size	 oktag_to_io,.Lfe1-oktag_to_io
-	.align 	2
-.globl oktag_from_io
-	.type	 oktag_from_io,@function
-oktag_from_io:
-	link.w %a6,#0
-	move.l %d2,-(%sp)
-	move.l 8(%a6),%d1
-	move.l 12(%a6),%a1
-	move.l %d1,%a0
-	move.l 16(%a6),%d0
-	addq.l #3,%d0
-	lsr.l #2,%d0
-	subq.l #1,%d0
-	moveq.l #-1,%d2
-	cmp.l %d0,%d2
-	jbeq .L9
-.L11:
-exp2:
-	move.l (%a1),(%a0)+
-	dbra %d0,.L11
-	clr.w %d0
-	subq.l #1,%d0
-	jbcc .L11
-.L9:
-ret2:
-	move.l %a0,%d0
-	sub.l %d1,%d0
-	asr.l #2,%d0
-	move.l -4(%a6),%d2
-	unlk %a6
-	rts
-.Lfe2:
-	.size	 oktag_from_io,.Lfe2-oktag_from_io
-	.ident	"GCC: (GNU) 2.7.2.1"
-
-/*
- * Exception table.
- * Second longword shows where to jump when an exception at the addr the first
- * longword is pointing to is caught.
- */
-
-.section __ex_table,"a"
-	.align	2
-oktagon_except:
-	.long	exp1,ret1
-	.long	exp2,ret2
-
-#endif
-#endif
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 17b4a7c..0cd614a 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -35,7 +35,7 @@
 
 #define BOUNCE_SIZE			(64*1024)
 
-#define PS3ROM_MAX_SECTORS		(BOUNCE_SIZE / CD_FRAMESIZE)
+#define PS3ROM_MAX_SECTORS		(BOUNCE_SIZE >> 9)
 
 
 struct ps3rom_private {
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index adf9732..4894dc8 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -428,6 +428,19 @@
 	if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
 		return 0;
 
+	if (ha->sfp_data)
+		goto do_read;
+
+	ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+	    &ha->sfp_data_dma);
+	if (!ha->sfp_data) {
+		qla_printk(KERN_WARNING, ha,
+		    "Unable to allocate memory for SFP read-data.\n");
+		return 0;
+	}
+
+do_read:
+	memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
 	addr = 0xa0;
 	for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
 	    iter++, offset += SFP_BLOCK_SIZE) {
@@ -835,7 +848,7 @@
 static void
 qla2x00_get_host_speed(struct Scsi_Host *shost)
 {
-	scsi_qla_host_t *ha = shost_priv(shost);
+	scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
 	uint32_t speed = 0;
 
 	switch (ha->link_data_rate) {
@@ -848,6 +861,9 @@
 	case PORT_SPEED_4GB:
 		speed = 4;
 		break;
+	case PORT_SPEED_8GB:
+		speed = 8;
+		break;
 	}
 	fc_host_speed(shost) = speed;
 }
@@ -855,7 +871,7 @@
 static void
 qla2x00_get_host_port_type(struct Scsi_Host *shost)
 {
-	scsi_qla_host_t *ha = shost_priv(shost);
+	scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
 	uint32_t port_type = FC_PORTTYPE_UNKNOWN;
 
 	switch (ha->current_topology) {
@@ -965,7 +981,7 @@
 static struct fc_host_statistics *
 qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
 {
-	scsi_qla_host_t *ha = shost_priv(shost);
+	scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
 	int rval;
 	struct link_statistics *stats;
 	dma_addr_t stats_dma;
@@ -1049,7 +1065,7 @@
 static void
 qla2x00_get_host_port_state(struct Scsi_Host *shost)
 {
-	scsi_qla_host_t *ha = shost_priv(shost);
+	scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
 
 	if (!ha->flags.online)
 		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b72c7f1..3750319 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2041,8 +2041,6 @@
 #define VP_RET_CODE_NO_MEM		5
 #define VP_RET_CODE_NOT_FOUND		6
 
-#define to_qla_parent(x) (((x)->parent) ? (x)->parent : (x))
-
 /*
  * ISP operations
  */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index ba35fc2..193f688 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -66,6 +66,7 @@
 extern int num_hosts;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
+extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
 
 /*
  * Global Functions in qla_mid.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index d0633ca..d5c7853 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -925,6 +925,16 @@
 {
 	int rval;
 	uint32_t srisc_address = 0;
+	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+	unsigned long flags;
+
+	if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
+		/* Disable SRAM, Instruction RAM and GP RAM parity.  */
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		WRT_REG_WORD(&reg->hccr, (HCCR_ENABLE_PARITY + 0x0));
+		RD_REG_WORD(&reg->hccr);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	}
 
 	/* Load firmware sequences */
 	rval = ha->isp_ops->load_risc(ha, &srisc_address);
@@ -968,6 +978,19 @@
 		}
 	}
 
+	if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
+		/* Enable proper parity. */
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		if (IS_QLA2300(ha))
+			/* SRAM parity */
+			WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x1);
+		else
+			/* SRAM, Instruction RAM and GP RAM parity */
+			WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x7);
+		RD_REG_WORD(&reg->hccr);
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	}
+
 	if (rval) {
 		DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
 		    ha->host_no));
@@ -3213,9 +3236,6 @@
 qla2x00_abort_isp(scsi_qla_host_t *ha)
 {
 	int rval;
-	unsigned long flags = 0;
-	uint16_t       cnt;
-	srb_t          *sp;
 	uint8_t        status = 0;
 
 	if (ha->flags.online) {
@@ -3236,19 +3256,8 @@
 				    LOOP_DOWN_TIME);
 		}
 
-		spin_lock_irqsave(&ha->hardware_lock, flags);
 		/* Requeue all commands in outstanding command list. */
-		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-			sp = ha->outstanding_cmds[cnt];
-			if (sp) {
-				ha->outstanding_cmds[cnt] = NULL;
-				sp->flags = 0;
-				sp->cmd->result = DID_RESET << 16;
-				sp->cmd->host_scribble = (unsigned char *)NULL;
-				qla2x00_sp_compl(ha, sp);
-			}
-		}
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+		qla2x00_abort_all_cmds(ha, DID_RESET << 16);
 
 		ha->isp_ops->get_flash_version(ha, ha->request_ring);
 
@@ -3273,6 +3282,7 @@
 			clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
 
 			if (ha->eft) {
+				memset(ha->eft, 0, EFT_SIZE);
 				rval = qla2x00_enable_eft_trace(ha,
 				    ha->eft_dma, EFT_NUM_BUFFERS);
 				if (rval) {
@@ -3357,60 +3367,15 @@
 qla2x00_restart_isp(scsi_qla_host_t *ha)
 {
 	uint8_t		status = 0;
-	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
-	unsigned long	flags = 0;
 	uint32_t wait_time;
 
 	/* If firmware needs to be loaded */
 	if (qla2x00_isp_firmware(ha)) {
 		ha->flags.online = 0;
-		if (!(status = ha->isp_ops->chip_diag(ha))) {
-			if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-				status = qla2x00_setup_chip(ha);
-				goto done;
-			}
-
-			spin_lock_irqsave(&ha->hardware_lock, flags);
-
-			if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
-			    !IS_QLA25XX(ha)) {
-				/*
-				 * Disable SRAM, Instruction RAM and GP RAM
-				 * parity.
-				 */
-				WRT_REG_WORD(&reg->hccr,
-				    (HCCR_ENABLE_PARITY + 0x0));
-				RD_REG_WORD(&reg->hccr);
-			}
-
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
+		if (!(status = ha->isp_ops->chip_diag(ha)))
 			status = qla2x00_setup_chip(ha);
-
-			spin_lock_irqsave(&ha->hardware_lock, flags);
-
-			if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
-			    !IS_QLA25XX(ha)) {
-				/* Enable proper parity */
-				if (IS_QLA2300(ha))
-					/* SRAM parity */
-					WRT_REG_WORD(&reg->hccr,
-					    (HCCR_ENABLE_PARITY + 0x1));
-				else
-					/*
-					 * SRAM, Instruction RAM and GP RAM
-					 * parity.
-					 */
-					WRT_REG_WORD(&reg->hccr,
-					    (HCCR_ENABLE_PARITY + 0x7));
-				RD_REG_WORD(&reg->hccr);
-			}
-
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-		}
 	}
 
- done:
 	if (!status && !(status = qla2x00_init_rings(ha))) {
 		clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
 		if (!(status = qla2x00_fw_ready(ha))) {
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 8e3b044..5d1a3f7 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -119,6 +119,13 @@
 	qla2x00_get_firmware_state(ha, &fw_state);
 }
 
+static __inline__ scsi_qla_host_t * to_qla_parent(scsi_qla_host_t *);
+static __inline__ scsi_qla_host_t *
+to_qla_parent(scsi_qla_host_t *ha)
+{
+	return ha->parent ? ha->parent : ha;
+}
+
 /**
  * qla2x00_issue_marker() - Issue a Marker IOCB if necessary.
  * @ha: HA context
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 642a0c3f..14e6f22 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1815,6 +1815,8 @@
 qla2x00_request_irqs(scsi_qla_host_t *ha)
 {
 	int ret;
+	device_reg_t __iomem *reg = ha->iobase;
+	unsigned long flags;
 
 	/* If possible, enable MSI-X. */
 	if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
@@ -1846,7 +1848,7 @@
 		DEBUG2(qla_printk(KERN_INFO, ha,
 		    "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
 		    ha->fw_attributes));
-		return ret;
+		goto clear_risc_ints;
 	}
 	qla_printk(KERN_WARNING, ha,
 	    "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
@@ -1864,15 +1866,30 @@
 
 	ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
 	    IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
-	if (!ret) {
-		ha->flags.inta_enabled = 1;
-		ha->host->irq = ha->pdev->irq;
-	} else {
+	if (ret) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to reserve interrupt %d already in use.\n",
 		    ha->pdev->irq);
+		goto fail;
 	}
+	ha->flags.inta_enabled = 1;
+	ha->host->irq = ha->pdev->irq;
+clear_risc_ints:
 
+	ha->isp_ops->disable_intrs(ha);
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	if (IS_FWI2_CAPABLE(ha)) {
+		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
+		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
+	} else {
+		WRT_REG_WORD(&reg->isp.semaphore, 0);
+		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
+		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	ha->isp_ops->enable_intrs(ha);
+
+fail:
 	return ret;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 0c10c0b..99d29ff 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -980,7 +980,7 @@
 	DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
 	    ha->host_no));
 
-	if (ha->fw_attributes & BIT_2)
+	if (ha->flags.npiv_supported)
 		mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE;
 	else
 		mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 8f69caf..3c1b433 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -204,10 +204,8 @@
 
 static void qla2x00_rst_aen(scsi_qla_host_t *);
 
-static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
+static int qla2x00_mem_alloc(scsi_qla_host_t *);
 static void qla2x00_mem_free(scsi_qla_host_t *ha);
-static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
-static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
 static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
 
 /* -------------------------------------------------------------------------- */
@@ -1117,6 +1115,27 @@
 	return ha->isp_ops->abort_target(reset_fcport);
 }
 
+void
+qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res)
+{
+	int cnt;
+	unsigned long flags;
+	srb_t *sp;
+
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+		sp = ha->outstanding_cmds[cnt];
+		if (sp) {
+			ha->outstanding_cmds[cnt] = NULL;
+			sp->flags = 0;
+			sp->cmd->result = res;
+			sp->cmd->host_scribble = (unsigned char *)NULL;
+			qla2x00_sp_compl(ha, sp);
+		}
+	}
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
 static int
 qla2xxx_slave_alloc(struct scsi_device *sdev)
 {
@@ -1557,10 +1576,8 @@
 qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int	ret = -ENODEV;
-	device_reg_t __iomem *reg;
 	struct Scsi_Host *host;
 	scsi_qla_host_t *ha;
-	unsigned long	flags = 0;
 	char pci_info[30];
 	char fw_str[30];
 	struct scsi_host_template *sht;
@@ -1608,6 +1625,7 @@
 	ha->parent = NULL;
 	ha->bars = bars;
 	ha->mem_only = mem_only;
+	spin_lock_init(&ha->hardware_lock);
 
 	/* Set ISP-type information. */
 	qla2x00_set_isp_flags(ha);
@@ -1621,8 +1639,6 @@
 	    "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
 	    ha->iobase);
 
-	spin_lock_init(&ha->hardware_lock);
-
 	ha->prev_topology = 0;
 	ha->init_cb_size = sizeof(init_cb_t);
 	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx;
@@ -1751,34 +1767,6 @@
 	DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
 	    ha->host_no, ha));
 
-	ha->isp_ops->disable_intrs(ha);
-
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	reg = ha->iobase;
-	if (IS_FWI2_CAPABLE(ha)) {
-		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
-		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
-	} else {
-		WRT_REG_WORD(&reg->isp.semaphore, 0);
-		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
-		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
-
-		/* Enable proper parity */
-		if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) {
-			if (IS_QLA2300(ha))
-				/* SRAM parity */
-				WRT_REG_WORD(&reg->isp.hccr,
-				    (HCCR_ENABLE_PARITY + 0x1));
-			else
-				/* SRAM, Instruction RAM and GP RAM parity */
-				WRT_REG_WORD(&reg->isp.hccr,
-				    (HCCR_ENABLE_PARITY + 0x7));
-		}
-	}
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-	ha->isp_ops->enable_intrs(ha);
-
 	pci_set_drvdata(pdev, ha);
 
 	ha->flags.init_done = 1;
@@ -1848,10 +1836,14 @@
 static void
 qla2x00_free_device(scsi_qla_host_t *ha)
 {
+	qla2x00_abort_all_cmds(ha, DID_NO_CONNECT << 16);
+
 	/* Disable timer */
 	if (ha->timer_active)
 		qla2x00_stop_timer(ha);
 
+	ha->flags.online = 0;
+
 	/* Kill the kernel thread for this host */
 	if (ha->dpc_thread) {
 		struct task_struct *t = ha->dpc_thread;
@@ -1870,8 +1862,6 @@
 	if (ha->eft)
 		qla2x00_disable_eft_trace(ha);
 
-	ha->flags.online = 0;
-
 	/* Stop currently executing firmware. */
 	qla2x00_try_to_stop_firmware(ha);
 
@@ -2010,196 +2000,109 @@
 *
 * Returns:
 *      0  = success.
-*      1  = failure.
+*      !0  = failure.
 */
-static uint8_t
+static int
 qla2x00_mem_alloc(scsi_qla_host_t *ha)
 {
 	char	name[16];
-	uint8_t   status = 1;
-	int	retry= 10;
 
-	do {
-		/*
-		 * This will loop only once if everything goes well, else some
-		 * number of retries will be performed to get around a kernel
-		 * bug where available mem is not allocated until after a
-		 * little delay and a retry.
-		 */
-		ha->request_ring = dma_alloc_coherent(&ha->pdev->dev,
-		    (ha->request_q_length + 1) * sizeof(request_t),
-		    &ha->request_dma, GFP_KERNEL);
-		if (ha->request_ring == NULL) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - request_ring\n");
+	ha->request_ring = dma_alloc_coherent(&ha->pdev->dev,
+	    (ha->request_q_length + 1) * sizeof(request_t), &ha->request_dma,
+	    GFP_KERNEL);
+	if (!ha->request_ring)
+		goto fail;
 
-			qla2x00_mem_free(ha);
-			msleep(100);
+	ha->response_ring = dma_alloc_coherent(&ha->pdev->dev,
+	    (ha->response_q_length + 1) * sizeof(response_t),
+	    &ha->response_dma, GFP_KERNEL);
+	if (!ha->response_ring)
+		goto fail_free_request_ring;
 
-			continue;
-		}
+	ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
+	    &ha->gid_list_dma, GFP_KERNEL);
+	if (!ha->gid_list)
+		goto fail_free_response_ring;
 
-		ha->response_ring = dma_alloc_coherent(&ha->pdev->dev,
-		    (ha->response_q_length + 1) * sizeof(response_t),
-		    &ha->response_dma, GFP_KERNEL);
-		if (ha->response_ring == NULL) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - response_ring\n");
+	ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
+	    &ha->init_cb_dma, GFP_KERNEL);
+	if (!ha->init_cb)
+		goto fail_free_gid_list;
 
-			qla2x00_mem_free(ha);
-			msleep(100);
+	snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,
+	    ha->host_no);
+	ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
+	    DMA_POOL_SIZE, 8, 0);
+	if (!ha->s_dma_pool)
+		goto fail_free_init_cb;
 
-			continue;
-		}
+	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
+	if (!ha->srb_mempool)
+		goto fail_free_s_dma_pool;
 
-		ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
-		    &ha->gid_list_dma, GFP_KERNEL);
-		if (ha->gid_list == NULL) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - gid_list\n");
+	/* Get memory for cached NVRAM */
+	ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL);
+	if (!ha->nvram)
+		goto fail_free_srb_mempool;
 
-			qla2x00_mem_free(ha);
-			msleep(100);
+	/* Allocate memory for SNS commands */
+	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
+		/* Get consistent memory allocated for SNS commands */
+		ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
+		    sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL);
+		if (!ha->sns_cmd)
+			goto fail_free_nvram;
+	} else {
+		/* Get consistent memory allocated for MS IOCB */
+		ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+		    &ha->ms_iocb_dma);
+		if (!ha->ms_iocb)
+			goto fail_free_nvram;
 
-			continue;
-		}
-
-		/* get consistent memory allocated for init control block */
-		ha->init_cb = dma_alloc_coherent(&ha->pdev->dev,
-		    ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL);
-		if (ha->init_cb == NULL) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - init_cb\n");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-		memset(ha->init_cb, 0, ha->init_cb_size);
-
-		snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,
-		    ha->host_no);
-		ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
-		    DMA_POOL_SIZE, 8, 0);
-		if (ha->s_dma_pool == NULL) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - s_dma_pool\n");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-
-		if (qla2x00_allocate_sp_pool(ha)) {
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - "
-			    "qla2x00_allocate_sp_pool()\n");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-
-		/* Allocate memory for SNS commands */
-		if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-			/* Get consistent memory allocated for SNS commands */
-			ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
-			    sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma,
-			    GFP_KERNEL);
-			if (ha->sns_cmd == NULL) {
-				/* error */
-				qla_printk(KERN_WARNING, ha,
-				    "Memory Allocation failed - sns_cmd\n");
-
-				qla2x00_mem_free(ha);
-				msleep(100);
-
-				continue;
-			}
-			memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt));
-		} else {
-			/* Get consistent memory allocated for MS IOCB */
-			ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
-			    &ha->ms_iocb_dma);
-			if (ha->ms_iocb == NULL) {
-				/* error */
-				qla_printk(KERN_WARNING, ha,
-				    "Memory Allocation failed - ms_iocb\n");
-
-				qla2x00_mem_free(ha);
-				msleep(100);
-
-				continue;
-			}
-			memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t));
-
-			/*
-			 * Get consistent memory allocated for CT SNS
-			 * commands
-			 */
-			ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
-			    sizeof(struct ct_sns_pkt), &ha->ct_sns_dma,
-			    GFP_KERNEL);
-			if (ha->ct_sns == NULL) {
-				/* error */
-				qla_printk(KERN_WARNING, ha,
-				    "Memory Allocation failed - ct_sns\n");
-
-				qla2x00_mem_free(ha);
-				msleep(100);
-
-				continue;
-			}
-			memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));
-
-			if (IS_FWI2_CAPABLE(ha)) {
-				/*
-				 * Get consistent memory allocated for SFP
-				 * block.
-				 */
-				ha->sfp_data = dma_pool_alloc(ha->s_dma_pool,
-				    GFP_KERNEL, &ha->sfp_data_dma);
-				if (ha->sfp_data == NULL) {
-					qla_printk(KERN_WARNING, ha,
-					    "Memory Allocation failed - "
-					    "sfp_data\n");
-
-					qla2x00_mem_free(ha);
-					msleep(100);
-
-					continue;
-				}
-				memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
-			}
-		}
-
-		/* Get memory for cached NVRAM */
-		ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL);
-		if (ha->nvram == NULL) {
-			/* error */
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - nvram cache\n");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-
-		/* Done all allocations without any error. */
-		status = 0;
-
-	} while (retry-- && status != 0);
-
-	if (status) {
-		printk(KERN_WARNING
-			"%s(): **** FAILED ****\n", __func__);
+		/* Get consistent memory allocated for CT SNS commands */
+		ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
+		    sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
+		if (!ha->ct_sns)
+			goto fail_free_ms_iocb;
 	}
 
-	return(status);
+	return 0;
+
+fail_free_ms_iocb:
+	dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
+	ha->ms_iocb = NULL;
+	ha->ms_iocb_dma = 0;
+fail_free_nvram:
+	kfree(ha->nvram);
+	ha->nvram = NULL;
+fail_free_srb_mempool:
+	mempool_destroy(ha->srb_mempool);
+	ha->srb_mempool = NULL;
+fail_free_s_dma_pool:
+	dma_pool_destroy(ha->s_dma_pool);
+	ha->s_dma_pool = NULL;
+fail_free_init_cb:
+	dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
+	    ha->init_cb_dma);
+	ha->init_cb = NULL;
+	ha->init_cb_dma = 0;
+fail_free_gid_list:
+	dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
+	    ha->gid_list_dma);
+	ha->gid_list = NULL;
+	ha->gid_list_dma = 0;
+fail_free_response_ring:
+	dma_free_coherent(&ha->pdev->dev, (ha->response_q_length + 1) *
+	    sizeof(response_t), ha->response_ring, ha->response_dma);
+	ha->response_ring = NULL;
+	ha->response_dma = 0;
+fail_free_request_ring:
+	dma_free_coherent(&ha->pdev->dev, (ha->request_q_length + 1) *
+	    sizeof(request_t), ha->request_ring, ha->request_dma);
+	ha->request_ring = NULL;
+	ha->request_dma = 0;
+fail:
+	return -ENOMEM;
 }
 
 /*
@@ -2215,14 +2118,8 @@
 	struct list_head	*fcpl, *fcptemp;
 	fc_port_t	*fcport;
 
-	if (ha == NULL) {
-		/* error */
-		DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__));
-		return;
-	}
-
-	/* free sp pool */
-	qla2x00_free_sp_pool(ha);
+	if (ha->srb_mempool)
+		mempool_destroy(ha->srb_mempool);
 
 	if (ha->fce)
 		dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
@@ -2270,6 +2167,7 @@
 		    (ha->request_q_length + 1) * sizeof(request_t),
 		    ha->request_ring, ha->request_dma);
 
+	ha->srb_mempool = NULL;
 	ha->eft = NULL;
 	ha->eft_dma = 0;
 	ha->sns_cmd = NULL;
@@ -2308,44 +2206,6 @@
 	kfree(ha->nvram);
 }
 
-/*
- * qla2x00_allocate_sp_pool
- * 	 This routine is called during initialization to allocate
- *  	 memory for local srb_t.
- *
- * Input:
- *	 ha   = adapter block pointer.
- *
- * Context:
- *      Kernel context.
- */
-static int
-qla2x00_allocate_sp_pool(scsi_qla_host_t *ha)
-{
-	int      rval;
-
-	rval = QLA_SUCCESS;
-	ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
-	if (ha->srb_mempool == NULL) {
-		qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n");
-		rval = QLA_FUNCTION_FAILED;
-	}
-	return (rval);
-}
-
-/*
- *  This routine frees all adapter allocated memory.
- *
- */
-static void
-qla2x00_free_sp_pool( scsi_qla_host_t *ha)
-{
-	if (ha->srb_mempool) {
-		mempool_destroy(ha->srb_mempool);
-		ha->srb_mempool = NULL;
-	}
-}
-
 /**************************************************************************
 * qla2x00_do_dpc
 *   This kernel thread is a task that is schedule by the interrupt handler
@@ -2367,6 +2227,9 @@
 	fc_port_t	*fcport;
 	uint8_t		status;
 	uint16_t	next_loopid;
+	struct scsi_qla_host *vha;
+	int             i;
+
 
 	ha = (scsi_qla_host_t *)data;
 
@@ -2409,6 +2272,18 @@
 				}
 				clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
 			}
+
+			for_each_mapped_vp_idx(ha, i) {
+				list_for_each_entry(vha, &ha->vp_list,
+				    vp_list) {
+					if (i == vha->vp_idx) {
+						set_bit(ISP_ABORT_NEEDED,
+						    &vha->dpc_flags);
+						break;
+					}
+				}
+			}
+
 			DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n",
 			    ha->host_no));
 		}
@@ -3029,3 +2904,4 @@
 MODULE_FIRMWARE(FW_FILE_ISP2300);
 MODULE_FIRMWARE(FW_FILE_ISP2322);
 MODULE_FIRMWARE(FW_FILE_ISP24XX);
+MODULE_FIRMWARE(FW_FILE_ISP25XX);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index b68fb73..26822c8 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -893,6 +893,8 @@
 	}
 }
 
+#define PIO_REG(h, r) ((h)->pio_address + offsetof(struct device_reg_2xxx, r))
+
 void
 qla2x00_beacon_blink(struct scsi_qla_host *ha)
 {
@@ -902,15 +904,12 @@
 	unsigned long flags;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
-	if (ha->pio_address)
-		reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
-
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
 	/* Save the Original GPIOE. */
 	if (ha->pio_address) {
-		gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
-		gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
+		gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe));
+		gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod));
 	} else {
 		gpio_enable = RD_REG_WORD(&reg->gpioe);
 		gpio_data = RD_REG_WORD(&reg->gpiod);
@@ -920,7 +919,7 @@
 	gpio_enable |= GPIO_LED_MASK;
 
 	if (ha->pio_address) {
-		WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
+		WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable);
 	} else {
 		WRT_REG_WORD(&reg->gpioe, gpio_enable);
 		RD_REG_WORD(&reg->gpioe);
@@ -936,7 +935,7 @@
 
 	/* Set the modified gpio_data values */
 	if (ha->pio_address) {
-		WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
+		WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data);
 	} else {
 		WRT_REG_WORD(&reg->gpiod, gpio_data);
 		RD_REG_WORD(&reg->gpiod);
@@ -962,14 +961,11 @@
 		return QLA_FUNCTION_FAILED;
 	}
 
-	if (ha->pio_address)
-		reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
-
 	/* Turn off LEDs. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	if (ha->pio_address) {
-		gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
-		gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
+		gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe));
+		gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod));
 	} else {
 		gpio_enable = RD_REG_WORD(&reg->gpioe);
 		gpio_data = RD_REG_WORD(&reg->gpiod);
@@ -978,7 +974,7 @@
 
 	/* Set the modified gpio_enable values. */
 	if (ha->pio_address) {
-		WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
+		WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable);
 	} else {
 		WRT_REG_WORD(&reg->gpioe, gpio_enable);
 		RD_REG_WORD(&reg->gpioe);
@@ -987,7 +983,7 @@
 	/* Clear out previously set LED colour. */
 	gpio_data &= ~GPIO_LED_MASK;
 	if (ha->pio_address) {
-		WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
+		WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data);
 	} else {
 		WRT_REG_WORD(&reg->gpiod, gpio_data);
 		RD_REG_WORD(&reg->gpiod);
@@ -1244,13 +1240,12 @@
 	if (ha->pio_address) {
 		uint16_t data2;
 
-		reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
-		WRT_REG_WORD_PIO(&reg->flash_address, (uint16_t)addr);
+		WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr);
 		do {
-			data = RD_REG_WORD_PIO(&reg->flash_data);
+			data = RD_REG_WORD_PIO(PIO_REG(ha, flash_data));
 			barrier();
 			cpu_relax();
-			data2 = RD_REG_WORD_PIO(&reg->flash_data);
+			data2 = RD_REG_WORD_PIO(PIO_REG(ha, flash_data));
 		} while (data != data2);
 	} else {
 		WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
@@ -1304,9 +1299,8 @@
 
 	/* Always perform IO mapped accesses to the FLASH registers. */
 	if (ha->pio_address) {
-		reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
-		WRT_REG_WORD_PIO(&reg->flash_address, (uint16_t)addr);
-		WRT_REG_WORD_PIO(&reg->flash_data, (uint16_t)data);
+		WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr);
+		WRT_REG_WORD_PIO(PIO_REG(ha, flash_data), (uint16_t)data);
 	} else {
 		WRT_REG_WORD(&reg->flash_address, (uint16_t)addr);
 		RD_REG_WORD(&reg->ctrl_status);		/* PCI Posting. */
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 2c2f6b4..c5742cc 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.02.00-k7"
+#define QLA2XXX_VERSION      "8.02.00-k8"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	2
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 49925f9..10b3b9a 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1306,6 +1306,7 @@
 		atomic_set(&ddb_entry->relogin_timer, 0);
 		clear_bit(DF_RELOGIN, &ddb_entry->flags);
 		clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
+		iscsi_unblock_session(ddb_entry->sess);
 		iscsi_session_event(ddb_entry->sess,
 				    ISCSI_KEVENT_CREATE_SESSION);
 		/*
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 2e2b9fe..c3c59d7 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -63,8 +63,6 @@
 				  enum iscsi_param param, char *buf);
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
 				  enum iscsi_host_param param, char *buf);
-static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag);
-static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
 
 /*
@@ -91,6 +89,8 @@
 	.slave_alloc		= qla4xxx_slave_alloc,
 	.slave_destroy		= qla4xxx_slave_destroy,
 
+	.scan_finished		= iscsi_scan_finished,
+
 	.this_id		= -1,
 	.cmd_per_lun		= 3,
 	.use_clustering		= ENABLE_CLUSTERING,
@@ -116,8 +116,6 @@
 	.get_conn_param		= qla4xxx_conn_get_param,
 	.get_session_param	= qla4xxx_sess_get_param,
 	.get_host_param		= qla4xxx_host_get_param,
-	.start_conn		= qla4xxx_conn_start,
-	.stop_conn		= qla4xxx_conn_stop,
 	.session_recovery_timedout = qla4xxx_recovery_timedout,
 };
 
@@ -128,48 +126,19 @@
 	struct ddb_entry *ddb_entry = session->dd_data;
 	struct scsi_qla_host *ha = ddb_entry->ha;
 
-	DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count of (%d) "
-		      "secs exhausted, marking device DEAD.\n", ha->host_no,
-		      __func__, ddb_entry->fw_ddb_index,
-		      ha->port_down_retry_count));
+	if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
+		atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
 
-	atomic_set(&ddb_entry->state, DDB_STATE_DEAD);
+		DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count "
+			      "of (%d) secs exhausted, marking device DEAD.\n",
+			      ha->host_no, __func__, ddb_entry->fw_ddb_index,
+			      ha->port_down_retry_count));
 
-	DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc flags = "
-		      "0x%lx\n", ha->host_no, __func__, ha->dpc_flags));
-	queue_work(ha->dpc_thread, &ha->dpc_work);
-}
-
-static int qla4xxx_conn_start(struct iscsi_cls_conn *conn)
-{
-	struct iscsi_cls_session *session;
-	struct ddb_entry *ddb_entry;
-
-	session = iscsi_dev_to_session(conn->dev.parent);
-	ddb_entry = session->dd_data;
-
-	DEBUG2(printk("scsi%ld: %s: index [%d] starting conn\n",
-		      ddb_entry->ha->host_no, __func__,
-		      ddb_entry->fw_ddb_index));
-	iscsi_unblock_session(session);
-	return 0;
-}
-
-static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag)
-{
-	struct iscsi_cls_session *session;
-	struct ddb_entry *ddb_entry;
-
-	session = iscsi_dev_to_session(conn->dev.parent);
-	ddb_entry = session->dd_data;
-
-	DEBUG2(printk("scsi%ld: %s: index [%d] stopping conn\n",
-		      ddb_entry->ha->host_no, __func__,
-		      ddb_entry->fw_ddb_index));
-	if (flag == STOP_CONN_RECOVER)
-		iscsi_block_session(session);
-	else
-		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+		DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc "
+			      "flags = 0x%lx\n",
+			      ha->host_no, __func__, ha->dpc_flags));
+		queue_work(ha->dpc_thread, &ha->dpc_work);
+	}
 }
 
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
@@ -308,6 +277,9 @@
 		DEBUG2(printk(KERN_ERR "Could not add connection.\n"));
 		return -ENOMEM;
 	}
+
+	/* finally ready to go */
+	iscsi_unblock_session(ddb_entry->sess);
 	return 0;
 }
 
@@ -364,6 +336,7 @@
 	DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n",
 		      ha->host_no, ddb_entry->bus, ddb_entry->target,
 		      ddb_entry->fw_ddb_index));
+	iscsi_block_session(ddb_entry->sess);
 	iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED);
 }
 
@@ -430,9 +403,21 @@
 {
 	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
 	struct ddb_entry *ddb_entry = cmd->device->hostdata;
+	struct iscsi_cls_session *sess = ddb_entry->sess;
 	struct srb *srb;
 	int rval;
 
+	if (!sess) {
+		cmd->result = DID_IMM_RETRY << 16;
+		goto qc_fail_command;
+	}
+
+	rval = iscsi_session_chkready(sess);
+	if (rval) {
+		cmd->result = rval;
+		goto qc_fail_command;
+	}
+
 	if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
 		if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) {
 			cmd->result = DID_NO_CONNECT << 16;
@@ -1323,7 +1308,7 @@
 	       qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),
 	       ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
 	       ha->patch_number, ha->build_number);
-
+	scsi_scan_host(host);
 	return 0;
 
 remove_host:
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index b35d194..fecba05 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -969,9 +969,10 @@
 EXPORT_SYMBOL(starget_for_each_device);
 
 /**
- * __starget_for_each_device  -  helper to walk all devices of a target
- *				 (UNLOCKED)
+ * __starget_for_each_device - helper to walk all devices of a target (UNLOCKED)
  * @starget:	target whose devices we want to iterate over.
+ * @data:	parameter for callback @fn()
+ * @fn:		callback function that is invoked for each device
  *
  * This traverses over each device of @starget.  It does _not_
  * take a reference on the scsi_device, so the whole loop must be
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f243fc3..135c1d0 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -301,7 +301,6 @@
 		page = sg_page(sg);
 		off = sg->offset;
 		len = sg->length;
- 		data_len += len;
 
 		while (len > 0 && data_len > 0) {
 			/*
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 0d7b4e7..fac7534 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -30,10 +30,10 @@
 #include <scsi/scsi_transport_iscsi.h>
 #include <scsi/iscsi_if.h>
 
-#define ISCSI_SESSION_ATTRS 18
-#define ISCSI_CONN_ATTRS 11
+#define ISCSI_SESSION_ATTRS 19
+#define ISCSI_CONN_ATTRS 13
 #define ISCSI_HOST_ATTRS 4
-#define ISCSI_TRANSPORT_VERSION "2.0-867"
+#define ISCSI_TRANSPORT_VERSION "2.0-868"
 
 struct iscsi_internal {
 	int daemon_pid;
@@ -127,12 +127,13 @@
 	memset(ihost, 0, sizeof(*ihost));
 	INIT_LIST_HEAD(&ihost->sessions);
 	mutex_init(&ihost->mutex);
+	atomic_set(&ihost->nr_scans, 0);
 
-	snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d",
+	snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
 		shost->host_no);
-	ihost->unbind_workq = create_singlethread_workqueue(
-						ihost->unbind_workq_name);
-	if (!ihost->unbind_workq)
+	ihost->scan_workq = create_singlethread_workqueue(
+						ihost->scan_workq_name);
+	if (!ihost->scan_workq)
 		return -ENOMEM;
 	return 0;
 }
@@ -143,7 +144,7 @@
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct iscsi_host *ihost = shost->shost_data;
 
-	destroy_workqueue(ihost->unbind_workq);
+	destroy_workqueue(ihost->scan_workq);
 	return 0;
 }
 
@@ -221,6 +222,54 @@
  * The following functions can be used by LLDs that allocate
  * their own scsi_hosts or by software iscsi LLDs
  */
+static struct {
+	int value;
+	char *name;
+} iscsi_session_state_names[] = {
+	{ ISCSI_SESSION_LOGGED_IN,	"LOGGED_IN" },
+	{ ISCSI_SESSION_FAILED,		"FAILED" },
+	{ ISCSI_SESSION_FREE,		"FREE" },
+};
+
+const char *iscsi_session_state_name(int state)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
+		if (iscsi_session_state_names[i].value == state) {
+			name = iscsi_session_state_names[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
+int iscsi_session_chkready(struct iscsi_cls_session *session)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&session->lock, flags);
+	switch (session->state) {
+	case ISCSI_SESSION_LOGGED_IN:
+		err = 0;
+		break;
+	case ISCSI_SESSION_FAILED:
+		err = DID_IMM_RETRY << 16;
+		break;
+	case ISCSI_SESSION_FREE:
+		err = DID_NO_CONNECT << 16;
+		break;
+	default:
+		err = DID_NO_CONNECT << 16;
+		break;
+	}
+	spin_unlock_irqrestore(&session->lock, flags);
+	return err;
+}
+EXPORT_SYMBOL_GPL(iscsi_session_chkready);
+
 static void iscsi_session_release(struct device *dev)
 {
 	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
@@ -236,6 +285,25 @@
 	return dev->release == iscsi_session_release;
 }
 
+/**
+ * iscsi_scan_finished - helper to report when running scans are done
+ * @shost: scsi host
+ * @time: scan run time
+ *
+ * This function can be used by drives like qla4xxx to report to the scsi
+ * layer when the scans it kicked off at module load time are done.
+ */
+int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+	struct iscsi_host *ihost = shost->shost_data;
+	/*
+	 * qla4xxx will have kicked off some session unblocks before calling
+	 * scsi_scan_host, so just wait for them to complete.
+	 */
+	return !atomic_read(&ihost->nr_scans);
+}
+EXPORT_SYMBOL_GPL(iscsi_scan_finished);
+
 static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
 			   uint id, uint lun)
 {
@@ -254,14 +322,50 @@
 	return 0;
 }
 
+static void iscsi_scan_session(struct work_struct *work)
+{
+	struct iscsi_cls_session *session =
+			container_of(work, struct iscsi_cls_session, scan_work);
+	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+	struct iscsi_host *ihost = shost->shost_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&session->lock, flags);
+	if (session->state != ISCSI_SESSION_LOGGED_IN) {
+		spin_unlock_irqrestore(&session->lock, flags);
+		goto done;
+	}
+	spin_unlock_irqrestore(&session->lock, flags);
+
+	scsi_scan_target(&session->dev, 0, session->target_id,
+			 SCAN_WILD_CARD, 1);
+done:
+	atomic_dec(&ihost->nr_scans);
+}
+
 static void session_recovery_timedout(struct work_struct *work)
 {
 	struct iscsi_cls_session *session =
 		container_of(work, struct iscsi_cls_session,
 			     recovery_work.work);
+	unsigned long flags;
 
-	dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
-		  "out after %d secs\n", session->recovery_tmo);
+	iscsi_cls_session_printk(KERN_INFO, session,
+				 "session recovery timed out after %d secs\n",
+				 session->recovery_tmo);
+
+	spin_lock_irqsave(&session->lock, flags);
+	switch (session->state) {
+	case ISCSI_SESSION_FAILED:
+		session->state = ISCSI_SESSION_FREE;
+		break;
+	case ISCSI_SESSION_LOGGED_IN:
+	case ISCSI_SESSION_FREE:
+		/* we raced with the unblock's flush */
+		spin_unlock_irqrestore(&session->lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&session->lock, flags);
 
 	if (session->transport->session_recovery_timedout)
 		session->transport->session_recovery_timedout(session);
@@ -269,16 +373,44 @@
 	scsi_target_unblock(&session->dev);
 }
 
-void iscsi_unblock_session(struct iscsi_cls_session *session)
+void __iscsi_unblock_session(struct iscsi_cls_session *session)
 {
 	if (!cancel_delayed_work(&session->recovery_work))
 		flush_workqueue(iscsi_eh_timer_workq);
 	scsi_target_unblock(&session->dev);
 }
+
+void iscsi_unblock_session(struct iscsi_cls_session *session)
+{
+	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+	struct iscsi_host *ihost = shost->shost_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&session->lock, flags);
+	session->state = ISCSI_SESSION_LOGGED_IN;
+	spin_unlock_irqrestore(&session->lock, flags);
+
+	__iscsi_unblock_session(session);
+	/*
+	 * Only do kernel scanning if the driver is properly hooked into
+	 * the async scanning code (drivers like iscsi_tcp do login and
+	 * scanning from userspace).
+	 */
+	if (shost->hostt->scan_finished) {
+		if (queue_work(ihost->scan_workq, &session->scan_work))
+			atomic_inc(&ihost->nr_scans);
+	}
+}
 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
 
 void iscsi_block_session(struct iscsi_cls_session *session)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&session->lock, flags);
+	session->state = ISCSI_SESSION_FAILED;
+	spin_unlock_irqrestore(&session->lock, flags);
+
 	scsi_target_block(&session->dev);
 	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
 			   session->recovery_tmo * HZ);
@@ -311,7 +443,7 @@
 	struct Scsi_Host *shost = iscsi_session_to_shost(session);
 	struct iscsi_host *ihost = shost->shost_data;
 
-	return queue_work(ihost->unbind_workq, &session->unbind_work);
+	return queue_work(ihost->scan_workq, &session->unbind_work);
 }
 
 struct iscsi_cls_session *
@@ -327,10 +459,13 @@
 
 	session->transport = transport;
 	session->recovery_tmo = 120;
+	session->state = ISCSI_SESSION_FREE;
 	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
 	INIT_LIST_HEAD(&session->host_list);
 	INIT_LIST_HEAD(&session->sess_list);
 	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
+	INIT_WORK(&session->scan_work, iscsi_scan_session);
+	spin_lock_init(&session->lock);
 
 	/* this is released in the dev's release function */
 	scsi_host_get(shost);
@@ -358,8 +493,8 @@
 		 session->sid);
 	err = device_add(&session->dev);
 	if (err) {
-		dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
-			   "register session's dev\n");
+		iscsi_cls_session_printk(KERN_ERR, session,
+					 "could not register session's dev\n");
 		goto release_host;
 	}
 	transport_register_device(&session->dev);
@@ -444,22 +579,28 @@
 	 * If we are blocked let commands flow again. The lld or iscsi
 	 * layer should set up the queuecommand to fail commands.
 	 */
-	iscsi_unblock_session(session);
-	iscsi_unbind_session(session);
+	spin_lock_irqsave(&session->lock, flags);
+	session->state = ISCSI_SESSION_FREE;
+	spin_unlock_irqrestore(&session->lock, flags);
+	__iscsi_unblock_session(session);
+	__iscsi_unbind_session(&session->unbind_work);
+
+	/* flush running scans */
+	flush_workqueue(ihost->scan_workq);
 	/*
 	 * If the session dropped while removing devices then we need to make
 	 * sure it is not blocked
 	 */
 	if (!cancel_delayed_work(&session->recovery_work))
 		flush_workqueue(iscsi_eh_timer_workq);
-	flush_workqueue(ihost->unbind_workq);
 
 	/* hw iscsi may not have removed all connections from session */
 	err = device_for_each_child(&session->dev, NULL,
 				    iscsi_iter_destroy_conn_fn);
 	if (err)
-		dev_printk(KERN_ERR, &session->dev, "iscsi: Could not delete "
-			   "all connections for session. Error %d.\n", err);
+		iscsi_cls_session_printk(KERN_ERR, session,
+					 "Could not delete all connections "
+					 "for session. Error %d.\n", err);
 
 	transport_unregister_device(&session->dev);
 	device_del(&session->dev);
@@ -531,8 +672,8 @@
 	conn->dev.release = iscsi_conn_release;
 	err = device_register(&conn->dev);
 	if (err) {
-		dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
-			   "connection's dev\n");
+		iscsi_cls_session_printk(KERN_ERR, session, "could not "
+					 "register connection's dev\n");
 		goto release_parent_ref;
 	}
 	transport_register_device(&conn->dev);
@@ -639,8 +780,8 @@
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (!skb) {
 		iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED);
-		dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
-			   "control PDU: OOM\n");
+		iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
+				      "control PDU: OOM\n");
 		return -ENOMEM;
 	}
 
@@ -661,20 +802,27 @@
 
 void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
 {
+	struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
 	struct nlmsghdr	*nlh;
 	struct sk_buff	*skb;
 	struct iscsi_uevent *ev;
 	struct iscsi_internal *priv;
 	int len = NLMSG_SPACE(sizeof(*ev));
+	unsigned long flags;
 
 	priv = iscsi_if_transport_lookup(conn->transport);
 	if (!priv)
 		return;
 
+	spin_lock_irqsave(&session->lock, flags);
+	if (session->state == ISCSI_SESSION_LOGGED_IN)
+		session->state = ISCSI_SESSION_FAILED;
+	spin_unlock_irqrestore(&session->lock, flags);
+
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (!skb) {
-		dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
-			  "conn error (%d)\n", error);
+		iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
+				      "conn error (%d)\n", error);
 		return;
 	}
 
@@ -688,8 +836,8 @@
 
 	iscsi_broadcast_skb(skb, GFP_ATOMIC);
 
-	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
-		   error);
+	iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
+			      error);
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_error);
 
@@ -744,8 +892,8 @@
 
 		skbstat = alloc_skb(len, GFP_ATOMIC);
 		if (!skbstat) {
-			dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
-				   "deliver stats: OOM\n");
+			iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
+					      "deliver stats: OOM\n");
 			return -ENOMEM;
 		}
 
@@ -801,8 +949,9 @@
 
 	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb) {
-		dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace "
-			  "of session event %u\n", event);
+		iscsi_cls_session_printk(KERN_ERR, session,
+					 "Cannot notify userspace of session "
+					 "event %u\n", event);
 		return -ENOMEM;
 	}
 
@@ -825,8 +974,8 @@
 		ev->r.unbind_session.sid = session->sid;
 		break;
 	default:
-		dev_printk(KERN_ERR, &session->dev, "Invalid event %u.\n",
-			   event);
+		iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
+					 "%u.\n", event);
 		kfree_skb(skb);
 		return -EINVAL;
 	}
@@ -837,8 +986,10 @@
 	 */
 	rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
 	if (rc < 0)
-		dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace "
-			  "of session event %u. Check iscsi daemon\n", event);
+		iscsi_cls_session_printk(KERN_ERR, session,
+					 "Cannot notify userspace of session "
+					 "event %u. Check iscsi daemon\n",
+					 event);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(iscsi_session_event);
@@ -871,16 +1022,15 @@
 
 	session = iscsi_session_lookup(ev->u.c_conn.sid);
 	if (!session) {
-		printk(KERN_ERR "iscsi: invalid session %d\n",
+		printk(KERN_ERR "iscsi: invalid session %d.\n",
 		       ev->u.c_conn.sid);
 		return -EINVAL;
 	}
 
 	conn = transport->create_conn(session, ev->u.c_conn.cid);
 	if (!conn) {
-		printk(KERN_ERR "iscsi: couldn't create a new "
-			   "connection for session %d\n",
-			   session->sid);
+		iscsi_cls_session_printk(KERN_ERR, session,
+					 "couldn't create a new connection.");
 		return -ENOMEM;
 	}
 
@@ -1246,6 +1396,15 @@
 iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
 iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
 
+static ssize_t
+show_priv_session_state(struct class_device *cdev, char *buf)
+{
+	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);
+	return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
+}
+static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+			NULL);
+
 #define iscsi_priv_session_attr_show(field, format)			\
 static ssize_t								\
 show_priv_session_##field(struct class_device *cdev, char *buf)		\
@@ -1472,6 +1631,7 @@
 	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);
 	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO);
 	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+	SETUP_PRIV_SESSION_RD_ATTR(state);
 
 	BUG_ON(count > ISCSI_SESSION_ATTRS);
 	priv->session_attrs[count] = NULL;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 51a5557..37df8bb 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -929,6 +929,7 @@
 	unsigned int xfer_size = scsi_bufflen(SCpnt);
  	unsigned int good_bytes = result ? 0 : xfer_size;
  	u64 start_lba = SCpnt->request->sector;
+	u64 end_lba = SCpnt->request->sector + (xfer_size / 512);
  	u64 bad_lba;
 	struct scsi_sense_hdr sshdr;
 	int sense_valid = 0;
@@ -967,26 +968,23 @@
 			goto out;
 		if (xfer_size <= SCpnt->device->sector_size)
 			goto out;
-		switch (SCpnt->device->sector_size) {
-		case 256:
+		if (SCpnt->device->sector_size < 512) {
+			/* only legitimate sector_size here is 256 */
 			start_lba <<= 1;
-			break;
-		case 512:
-			break;
-		case 1024:
-			start_lba >>= 1;
-			break;
-		case 2048:
-			start_lba >>= 2;
-			break;
-		case 4096:
-			start_lba >>= 3;
-			break;
-		default:
-			/* Print something here with limiting frequency. */
-			goto out;
-			break;
+			end_lba <<= 1;
+		} else {
+			/* be careful ... don't want any overflows */
+			u64 factor = SCpnt->device->sector_size / 512;
+			do_div(start_lba, factor);
+			do_div(end_lba, factor);
 		}
+
+		if (bad_lba < start_lba  || bad_lba >= end_lba)
+			/* the bad lba was reported incorrectly, we have
+			 * no idea where the error is
+			 */
+			goto out;
+
 		/* This computation should always be done in terms of
 		 * the resolution of the device's medium.
 		 */
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
new file mode 100644
index 0000000..2a6e4f4
--- /dev/null
+++ b/drivers/scsi/ses.c
@@ -0,0 +1,689 @@
+/*
+ * SCSI Enclosure Services
+ *
+ * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ *
+**-----------------------------------------------------------------------------
+**
+**  This program is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU General Public License
+**  version 2 as published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/enclosure.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_host.h>
+
+struct ses_device {
+	char *page1;
+	char *page2;
+	char *page10;
+	short page1_len;
+	short page2_len;
+	short page10_len;
+};
+
+struct ses_component {
+	u64 addr;
+	unsigned char *desc;
+};
+
+static int ses_probe(struct device *dev)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	int err = -ENODEV;
+
+	if (sdev->type != TYPE_ENCLOSURE)
+		goto out;
+
+	err = 0;
+	sdev_printk(KERN_NOTICE, sdev, "Attached Enclosure device\n");
+
+ out:
+	return err;
+}
+
+#define SES_TIMEOUT 30
+#define SES_RETRIES 3
+
+static int ses_recv_diag(struct scsi_device *sdev, int page_code,
+			 void *buf, int bufflen)
+{
+	char cmd[] = {
+		RECEIVE_DIAGNOSTIC,
+		1,		/* Set PCV bit */
+		page_code,
+		bufflen >> 8,
+		bufflen & 0xff,
+		0
+	};
+
+	return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
+				NULL, SES_TIMEOUT, SES_RETRIES);
+}
+
+static int ses_send_diag(struct scsi_device *sdev, int page_code,
+			 void *buf, int bufflen)
+{
+	u32 result;
+
+	char cmd[] = {
+		SEND_DIAGNOSTIC,
+		0x10,		/* Set PF bit */
+		0,
+		bufflen >> 8,
+		bufflen & 0xff,
+		0
+	};
+
+	result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen,
+				  NULL, SES_TIMEOUT, SES_RETRIES);
+	if (result)
+		sdev_printk(KERN_ERR, sdev, "SEND DIAGNOSTIC result: %8x\n",
+			    result);
+	return result;
+}
+
+static int ses_set_page2_descriptor(struct enclosure_device *edev,
+				      struct enclosure_component *ecomp,
+				      char *desc)
+{
+	int i, j, count = 0, descriptor = ecomp->number;
+	struct scsi_device *sdev = to_scsi_device(edev->cdev.dev);
+	struct ses_device *ses_dev = edev->scratch;
+	char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+	char *desc_ptr = ses_dev->page2 + 8;
+
+	/* Clear everything */
+	memset(desc_ptr, 0, ses_dev->page2_len - 8);
+	for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) {
+		for (j = 0; j < type_ptr[1]; j++) {
+			desc_ptr += 4;
+			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
+			    type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE)
+				continue;
+			if (count++ == descriptor) {
+				memcpy(desc_ptr, desc, 4);
+				/* set select */
+				desc_ptr[0] |= 0x80;
+				/* clear reserved, just in case */
+				desc_ptr[0] &= 0xf0;
+			}
+		}
+	}
+
+	return ses_send_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
+}
+
+static char *ses_get_page2_descriptor(struct enclosure_device *edev,
+				      struct enclosure_component *ecomp)
+{
+	int i, j, count = 0, descriptor = ecomp->number;
+	struct scsi_device *sdev = to_scsi_device(edev->cdev.dev);
+	struct ses_device *ses_dev = edev->scratch;
+	char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+	char *desc_ptr = ses_dev->page2 + 8;
+
+	ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
+
+	for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) {
+		for (j = 0; j < type_ptr[1]; j++) {
+			desc_ptr += 4;
+			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
+			    type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE)
+				continue;
+			if (count++ == descriptor)
+				return desc_ptr;
+		}
+	}
+	return NULL;
+}
+
+static void ses_get_fault(struct enclosure_device *edev,
+			  struct enclosure_component *ecomp)
+{
+	char *desc;
+
+	desc = ses_get_page2_descriptor(edev, ecomp);
+	ecomp->fault = (desc[3] & 0x60) >> 4;
+}
+
+static int ses_set_fault(struct enclosure_device *edev,
+			  struct enclosure_component *ecomp,
+			 enum enclosure_component_setting val)
+{
+	char desc[4] = {0 };
+
+	switch (val) {
+	case ENCLOSURE_SETTING_DISABLED:
+		/* zero is disabled */
+		break;
+	case ENCLOSURE_SETTING_ENABLED:
+		desc[2] = 0x02;
+		break;
+	default:
+		/* SES doesn't do the SGPIO blink settings */
+		return -EINVAL;
+	}
+
+	return ses_set_page2_descriptor(edev, ecomp, desc);
+}
+
+static void ses_get_status(struct enclosure_device *edev,
+			   struct enclosure_component *ecomp)
+{
+	char *desc;
+
+	desc = ses_get_page2_descriptor(edev, ecomp);
+	ecomp->status = (desc[0] & 0x0f);
+}
+
+static void ses_get_locate(struct enclosure_device *edev,
+			   struct enclosure_component *ecomp)
+{
+	char *desc;
+
+	desc = ses_get_page2_descriptor(edev, ecomp);
+	ecomp->locate = (desc[2] & 0x02) ? 1 : 0;
+}
+
+static int ses_set_locate(struct enclosure_device *edev,
+			  struct enclosure_component *ecomp,
+			  enum enclosure_component_setting val)
+{
+	char desc[4] = {0 };
+
+	switch (val) {
+	case ENCLOSURE_SETTING_DISABLED:
+		/* zero is disabled */
+		break;
+	case ENCLOSURE_SETTING_ENABLED:
+		desc[2] = 0x02;
+		break;
+	default:
+		/* SES doesn't do the SGPIO blink settings */
+		return -EINVAL;
+	}
+	return ses_set_page2_descriptor(edev, ecomp, desc);
+}
+
+static int ses_set_active(struct enclosure_device *edev,
+			  struct enclosure_component *ecomp,
+			  enum enclosure_component_setting val)
+{
+	char desc[4] = {0 };
+
+	switch (val) {
+	case ENCLOSURE_SETTING_DISABLED:
+		/* zero is disabled */
+		ecomp->active = 0;
+		break;
+	case ENCLOSURE_SETTING_ENABLED:
+		desc[2] = 0x80;
+		ecomp->active = 1;
+		break;
+	default:
+		/* SES doesn't do the SGPIO blink settings */
+		return -EINVAL;
+	}
+	return ses_set_page2_descriptor(edev, ecomp, desc);
+}
+
+static struct enclosure_component_callbacks ses_enclosure_callbacks = {
+	.get_fault		= ses_get_fault,
+	.set_fault		= ses_set_fault,
+	.get_status		= ses_get_status,
+	.get_locate		= ses_get_locate,
+	.set_locate		= ses_set_locate,
+	.set_active		= ses_set_active,
+};
+
+struct ses_host_edev {
+	struct Scsi_Host *shost;
+	struct enclosure_device *edev;
+};
+
+int ses_match_host(struct enclosure_device *edev, void *data)
+{
+	struct ses_host_edev *sed = data;
+	struct scsi_device *sdev;
+
+	if (!scsi_is_sdev_device(edev->cdev.dev))
+		return 0;
+
+	sdev = to_scsi_device(edev->cdev.dev);
+
+	if (sdev->host != sed->shost)
+		return 0;
+
+	sed->edev = edev;
+	return 1;
+}
+
+static void ses_process_descriptor(struct enclosure_component *ecomp,
+				   unsigned char *desc)
+{
+	int eip = desc[0] & 0x10;
+	int invalid = desc[0] & 0x80;
+	enum scsi_protocol proto = desc[0] & 0x0f;
+	u64 addr = 0;
+	struct ses_component *scomp = ecomp->scratch;
+	unsigned char *d;
+
+	scomp->desc = desc;
+
+	if (invalid)
+		return;
+
+	switch (proto) {
+	case SCSI_PROTOCOL_SAS:
+		if (eip)
+			d = desc + 8;
+		else
+			d = desc + 4;
+		/* only take the phy0 addr */
+		addr = (u64)d[12] << 56 |
+			(u64)d[13] << 48 |
+			(u64)d[14] << 40 |
+			(u64)d[15] << 32 |
+			(u64)d[16] << 24 |
+			(u64)d[17] << 16 |
+			(u64)d[18] << 8 |
+			(u64)d[19];
+		break;
+	default:
+		/* FIXME: Need to add more protocols than just SAS */
+		break;
+	}
+	scomp->addr = addr;
+}
+
+struct efd {
+	u64 addr;
+	struct device *dev;
+};
+
+static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
+				      void *data)
+{
+	struct efd *efd = data;
+	int i;
+	struct ses_component *scomp;
+
+	if (!edev->component[0].scratch)
+		return 0;
+
+	for (i = 0; i < edev->components; i++) {
+		scomp = edev->component[i].scratch;
+		if (scomp->addr != efd->addr)
+			continue;
+
+		enclosure_add_device(edev, i, efd->dev);
+		return 1;
+	}
+	return 0;
+}
+
+#define VPD_INQUIRY_SIZE 512
+
+static void ses_match_to_enclosure(struct enclosure_device *edev,
+				   struct scsi_device *sdev)
+{
+	unsigned char *buf = kmalloc(VPD_INQUIRY_SIZE, GFP_KERNEL);
+	unsigned char *desc;
+	int len;
+	struct efd efd = {
+		.addr = 0,
+	};
+	unsigned char cmd[] = {
+		INQUIRY,
+		1,
+		0x83,
+		VPD_INQUIRY_SIZE >> 8,
+		VPD_INQUIRY_SIZE & 0xff,
+		0
+	};
+
+	if (!buf)
+		return;
+
+	if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf,
+			     VPD_INQUIRY_SIZE, NULL, SES_TIMEOUT, SES_RETRIES))
+		goto free;
+
+	len = (buf[2] << 8) + buf[3];
+	desc = buf + 4;
+	while (desc < buf + len) {
+		enum scsi_protocol proto = desc[0] >> 4;
+		u8 code_set = desc[0] & 0x0f;
+		u8 piv = desc[1] & 0x80;
+		u8 assoc = (desc[1] & 0x30) >> 4;
+		u8 type = desc[1] & 0x0f;
+		u8 len = desc[3];
+
+		if (piv && code_set == 1 && assoc == 1 && code_set == 1
+		    && proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8)
+			efd.addr = (u64)desc[4] << 56 |
+				(u64)desc[5] << 48 |
+				(u64)desc[6] << 40 |
+				(u64)desc[7] << 32 |
+				(u64)desc[8] << 24 |
+				(u64)desc[9] << 16 |
+				(u64)desc[10] << 8 |
+				(u64)desc[11];
+
+		desc += len + 4;
+	}
+	if (!efd.addr)
+		goto free;
+
+	efd.dev = &sdev->sdev_gendev;
+
+	enclosure_for_each_device(ses_enclosure_find_by_addr, &efd);
+ free:
+	kfree(buf);
+}
+
+#define INIT_ALLOC_SIZE 32
+
+static int ses_intf_add(struct class_device *cdev,
+			struct class_interface *intf)
+{
+	struct scsi_device *sdev = to_scsi_device(cdev->dev);
+	struct scsi_device *tmp_sdev;
+	unsigned char *buf = NULL, *hdr_buf, *type_ptr, *desc_ptr,
+		*addl_desc_ptr;
+	struct ses_device *ses_dev;
+	u32 result;
+	int i, j, types, len, components = 0;
+	int err = -ENOMEM;
+	struct enclosure_device *edev;
+	struct ses_component *scomp;
+
+	if (!scsi_device_enclosure(sdev)) {
+		/* not an enclosure, but might be in one */
+		edev = 	enclosure_find(&sdev->host->shost_gendev);
+		if (edev) {
+			ses_match_to_enclosure(edev, sdev);
+			class_device_put(&edev->cdev);
+		}
+		return -ENODEV;
+	}
+
+	/* TYPE_ENCLOSURE prints a message in probe */
+	if (sdev->type != TYPE_ENCLOSURE)
+		sdev_printk(KERN_NOTICE, sdev, "Embedded Enclosure Device\n");
+
+	ses_dev = kzalloc(sizeof(*ses_dev), GFP_KERNEL);
+	hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
+	if (!hdr_buf || !ses_dev)
+		goto err_init_free;
+
+	result = ses_recv_diag(sdev, 1, hdr_buf, INIT_ALLOC_SIZE);
+	if (result)
+		goto recv_failed;
+
+	if (hdr_buf[1] != 0) {
+		/* FIXME: need subenclosure support; I've just never
+		 * seen a device with subenclosures and it makes the
+		 * traversal routines more complex */
+		sdev_printk(KERN_ERR, sdev,
+			"FIXME driver has no support for subenclosures (%d)\n",
+			buf[1]);
+		goto err_free;
+	}
+
+	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		goto err_free;
+
+	ses_dev->page1 = buf;
+	ses_dev->page1_len = len;
+
+	result = ses_recv_diag(sdev, 1, buf, len);
+	if (result)
+		goto recv_failed;
+
+	types = buf[10];
+	len = buf[11];
+
+	type_ptr = buf + 12 + len;
+
+	for (i = 0; i < types; i++, type_ptr += 4) {
+		if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
+		    type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
+			components += type_ptr[1];
+	}
+
+	result = ses_recv_diag(sdev, 2, hdr_buf, INIT_ALLOC_SIZE);
+	if (result)
+		goto recv_failed;
+
+	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		goto err_free;
+
+	/* make sure getting page 2 actually works */
+	result = ses_recv_diag(sdev, 2, buf, len);
+	if (result)
+		goto recv_failed;
+	ses_dev->page2 = buf;
+	ses_dev->page2_len = len;
+
+	/* The additional information page --- allows us
+	 * to match up the devices */
+	result = ses_recv_diag(sdev, 10, hdr_buf, INIT_ALLOC_SIZE);
+	if (result)
+		goto no_page10;
+
+	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		goto err_free;
+
+	result = ses_recv_diag(sdev, 10, buf, len);
+	if (result)
+		goto recv_failed;
+	ses_dev->page10 = buf;
+	ses_dev->page10_len = len;
+
+ no_page10:
+	scomp = kmalloc(sizeof(struct ses_component) * components, GFP_KERNEL);
+	if (!scomp)
+		goto  err_free;
+
+	edev = enclosure_register(cdev->dev, sdev->sdev_gendev.bus_id,
+				  components, &ses_enclosure_callbacks);
+	if (IS_ERR(edev)) {
+		err = PTR_ERR(edev);
+		goto err_free;
+	}
+
+	edev->scratch = ses_dev;
+	for (i = 0; i < components; i++)
+		edev->component[i].scratch = scomp++;
+
+	/* Page 7 for the descriptors is optional */
+	buf = NULL;
+	result = ses_recv_diag(sdev, 7, hdr_buf, INIT_ALLOC_SIZE);
+	if (result)
+		goto simple_populate;
+
+	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
+	/* add 1 for trailing '\0' we'll use */
+	buf = kzalloc(len + 1, GFP_KERNEL);
+	result = ses_recv_diag(sdev, 7, buf, len);
+	if (result) {
+ simple_populate:
+		kfree(buf);
+		buf = NULL;
+		desc_ptr = NULL;
+		addl_desc_ptr = NULL;
+	} else {
+		desc_ptr = buf + 8;
+		len = (desc_ptr[2] << 8) + desc_ptr[3];
+		/* skip past overall descriptor */
+		desc_ptr += len + 4;
+		addl_desc_ptr = ses_dev->page10 + 8;
+	}
+	type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+	components = 0;
+	for (i = 0; i < types; i++, type_ptr += 4) {
+		for (j = 0; j < type_ptr[1]; j++) {
+			char *name = NULL;
+			struct enclosure_component *ecomp;
+
+			if (desc_ptr) {
+				len = (desc_ptr[2] << 8) + desc_ptr[3];
+				desc_ptr += 4;
+				/* Add trailing zero - pushes into
+				 * reserved space */
+				desc_ptr[len] = '\0';
+				name = desc_ptr;
+			}
+			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
+			    type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE)
+				continue;
+			ecomp =	enclosure_component_register(edev,
+							     components++,
+							     type_ptr[0],
+							     name);
+			if (desc_ptr) {
+				desc_ptr += len;
+				if (!IS_ERR(ecomp))
+					ses_process_descriptor(ecomp,
+							       addl_desc_ptr);
+
+				if (addl_desc_ptr)
+					addl_desc_ptr += addl_desc_ptr[1] + 2;
+			}
+		}
+	}
+	kfree(buf);
+	kfree(hdr_buf);
+
+	/* see if there are any devices matching before
+	 * we found the enclosure */
+	shost_for_each_device(tmp_sdev, sdev->host) {
+		if (tmp_sdev->lun != 0 || scsi_device_enclosure(tmp_sdev))
+			continue;
+		ses_match_to_enclosure(edev, tmp_sdev);
+	}
+
+	return 0;
+
+ recv_failed:
+	sdev_printk(KERN_ERR, sdev, "Failed to get diagnostic page 0x%x\n",
+		    result);
+	err = -ENODEV;
+ err_free:
+	kfree(buf);
+	kfree(ses_dev->page10);
+	kfree(ses_dev->page2);
+	kfree(ses_dev->page1);
+ err_init_free:
+	kfree(ses_dev);
+	kfree(hdr_buf);
+	sdev_printk(KERN_ERR, sdev, "Failed to bind enclosure %d\n", err);
+	return err;
+}
+
+static int ses_remove(struct device *dev)
+{
+	return 0;
+}
+
+static void ses_intf_remove(struct class_device *cdev,
+			    struct class_interface *intf)
+{
+	struct scsi_device *sdev = to_scsi_device(cdev->dev);
+	struct enclosure_device *edev;
+	struct ses_device *ses_dev;
+
+	if (!scsi_device_enclosure(sdev))
+		return;
+
+	edev = enclosure_find(cdev->dev);
+	if (!edev)
+		return;
+
+	ses_dev = edev->scratch;
+	edev->scratch = NULL;
+
+	kfree(ses_dev->page1);
+	kfree(ses_dev->page2);
+	kfree(ses_dev);
+
+	kfree(edev->component[0].scratch);
+
+	class_device_put(&edev->cdev);
+	enclosure_unregister(edev);
+}
+
+static struct class_interface ses_interface = {
+	.add	= ses_intf_add,
+	.remove	= ses_intf_remove,
+};
+
+static struct scsi_driver ses_template = {
+	.owner			= THIS_MODULE,
+	.gendrv = {
+		.name		= "ses",
+		.probe		= ses_probe,
+		.remove		= ses_remove,
+	},
+};
+
+static int __init ses_init(void)
+{
+	int err;
+
+	err = scsi_register_interface(&ses_interface);
+	if (err)
+		return err;
+
+	err = scsi_register_driver(&ses_template.gendrv);
+	if (err)
+		goto out_unreg;
+
+	return 0;
+
+ out_unreg:
+	scsi_unregister_interface(&ses_interface);
+	return err;
+}
+
+static void __exit ses_exit(void)
+{
+	scsi_unregister_driver(&ses_template.gendrv);
+	scsi_unregister_interface(&ses_interface);
+}
+
+module_init(ses_init);
+module_exit(ses_exit);
+
+MODULE_ALIAS_SCSI_DEVICE(TYPE_ENCLOSURE);
+
+MODULE_AUTHOR("James Bottomley");
+MODULE_DESCRIPTION("SCSI Enclosure Services (ses) driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index aba28f3..e5156aa 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1160,23 +1160,22 @@
 	return (retval < 0) ? retval : 0;
 }
 
-static struct page *
-sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
+static int
+sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	Sg_fd *sfp;
-	struct page *page = NOPAGE_SIGBUS;
 	unsigned long offset, len, sa;
 	Sg_scatter_hold *rsv_schp;
 	struct scatterlist *sg;
 	int k;
 
 	if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data)))
-		return page;
+		return VM_FAULT_SIGBUS;
 	rsv_schp = &sfp->reserve;
-	offset = addr - vma->vm_start;
+	offset = vmf->pgoff << PAGE_SHIFT;
 	if (offset >= rsv_schp->bufflen)
-		return page;
-	SCSI_LOG_TIMEOUT(3, printk("sg_vma_nopage: offset=%lu, scatg=%d\n",
+		return VM_FAULT_SIGBUS;
+	SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n",
 				   offset, rsv_schp->k_use_sg));
 	sg = rsv_schp->buffer;
 	sa = vma->vm_start;
@@ -1185,21 +1184,21 @@
 		len = vma->vm_end - sa;
 		len = (len < sg->length) ? len : sg->length;
 		if (offset < len) {
+			struct page *page;
 			page = virt_to_page(page_address(sg_page(sg)) + offset);
 			get_page(page);	/* increment page count */
-			break;
+			vmf->page = page;
+			return 0; /* success */
 		}
 		sa += len;
 		offset -= len;
 	}
 
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return page;
+	return VM_FAULT_SIGBUS;
 }
 
 static struct vm_operations_struct sg_mmap_vm_ops = {
-	.nopage = sg_vma_nopage,
+	.fault = sg_vma_fault,
 };
 
 static int
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 50ba492..208565b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -163,6 +163,29 @@
 	mutex_unlock(&sr_ref_mutex);
 }
 
+/* identical to scsi_test_unit_ready except that it doesn't
+ * eat the NOT_READY returns for removable media */
+int sr_test_unit_ready(struct scsi_device *sdev, struct scsi_sense_hdr *sshdr)
+{
+	int retries = MAX_RETRIES;
+	int the_result;
+	u8 cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0 };
+
+	/* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION
+	 * conditions are gone, or a timeout happens
+	 */
+	do {
+		the_result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL,
+					      0, sshdr, SR_TIMEOUT,
+					      retries--);
+
+	} while (retries > 0 &&
+		 (!scsi_status_is_good(the_result) ||
+		  (scsi_sense_valid(sshdr) &&
+		   sshdr->sense_key == UNIT_ATTENTION)));
+	return the_result;
+}
+
 /*
  * This function checks to see if the media has been changed in the
  * CDROM drive.  It is possible that we have already sensed a change,
@@ -185,8 +208,7 @@
 	}
 
 	sshdr =  kzalloc(sizeof(*sshdr), GFP_KERNEL);
-	retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES,
-				      sshdr);
+	retval = sr_test_unit_ready(cd->device, sshdr);
 	if (retval || (scsi_sense_valid(sshdr) &&
 		       /* 0x3a is medium not present */
 		       sshdr->asc == 0x3a)) {
@@ -733,10 +755,8 @@
 {
 	unsigned char *buffer;
 	struct scsi_mode_data data;
-	unsigned char cmd[MAX_COMMAND_SIZE];
 	struct scsi_sense_hdr sshdr;
-	unsigned int the_result;
-	int retries, rc, n;
+	int rc, n;
 
 	static const char *loadmech[] =
 	{
@@ -758,23 +778,8 @@
 		return;
 	}
 
-	/* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION
-	 * conditions are gone, or a timeout happens
-	 */
-	retries = 0;
-	do {
-		memset((void *)cmd, 0, MAX_COMMAND_SIZE);
-		cmd[0] = TEST_UNIT_READY;
-
-		the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL,
-					       0, &sshdr, SR_TIMEOUT,
-					       MAX_RETRIES);
-
-		retries++;
-	} while (retries < 5 && 
-		 (!scsi_status_is_good(the_result) ||
-		  (scsi_sense_valid(&sshdr) &&
-		   sshdr.sense_key == UNIT_ATTENTION)));
+	/* eat unit attentions */
+	sr_test_unit_ready(cd->device, &sshdr);
 
 	/* ask for mode page 0x2a */
 	rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index 81fbc0b..1e144df 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -61,6 +61,7 @@
 int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
 
 int sr_is_xa(Scsi_CD *);
+int sr_test_unit_ready(struct scsi_device *sdev, struct scsi_sense_hdr *sshdr);
 
 /* sr_vendor.c */
 void sr_vendor_init(Scsi_CD *);
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index d5cebff..ae87d08 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -306,8 +306,7 @@
 		/* we have no changer support */
 		return -EINVAL;
 	}
-	if (0 == scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES,
-				      &sshdr))
+	if (0 == sr_test_unit_ready(cd->device, &sshdr))
 		return CDS_DISC_OK;
 
 	if (!cdrom_get_media_event(cdi, &med)) {
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 1bc4190..06152c7 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -1,392 +1,316 @@
-/* sun3x_esp.c:  EnhancedScsiProcessor Sun3x SCSI driver code.
+/* sun3x_esp.c: ESP front-end for Sun3x systems.
  *
- * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- *
- * Based on David S. Miller's esp driver
+ * Copyright (C) 2007,2008 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  */
 
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
 #include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
-
 #include <asm/sun3x.h>
+#include <asm/io.h>
+#include <asm/dma.h>
 #include <asm/dvma.h>
-#include <asm/irq.h>
 
-static void dma_barrier(struct NCR_ESP *esp);
-static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_drain(struct NCR_ESP *esp);
-static void dma_invalidate(struct NCR_ESP *esp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int  dma_irq_p(struct NCR_ESP *esp);
-static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr);
-static int  dma_ports_p(struct NCR_ESP *esp);
-static void dma_reset(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
-static void dma_advance_sg (Scsi_Cmnd *sp);
+/* DMA controller reg offsets */
+#define DMA_CSR		0x00UL	/* rw  DMA control/status register    0x00   */
+#define DMA_ADDR        0x04UL	/* rw  DMA transfer address register  0x04   */
+#define DMA_COUNT       0x08UL	/* rw  DMA transfer count register    0x08   */
+#define DMA_TEST        0x0cUL	/* rw  DMA test/debug register        0x0c   */
 
-/* Detecting ESP chips on the machine.  This is the simple and easy
- * version.
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME		"sun3x_esp"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_VERSION		"1.000"
+#define DRV_MODULE_RELDATE	"Nov 1, 2007"
+
+/*
+ * m68k always assumes readl/writel operate on little endian
+ * mmio space; this is wrong at least for Sun3x, so we
+ * need to workaround this until a proper way is found
  */
-int sun3x_esp_detect(struct scsi_host_template *tpnt)
+#if 0
+#define dma_read32(REG) \
+	readl(esp->dma_regs + (REG))
+#define dma_write32(VAL, REG) \
+	writel((VAL), esp->dma_regs + (REG))
+#else
+#define dma_read32(REG) \
+	*(volatile u32 *)(esp->dma_regs + (REG))
+#define dma_write32(VAL, REG) \
+	do { *(volatile u32 *)(esp->dma_regs + (REG)) = (VAL); } while (0)
+#endif
+
+static void sun3x_esp_write8(struct esp *esp, u8 val, unsigned long reg)
 {
-	struct NCR_ESP *esp;
-	struct ConfigDev *esp_dev;
-
-	esp_dev = 0;
-	esp = esp_allocate(tpnt, esp_dev, 0);
-
-	/* Do command transfer with DMA */
-	esp->do_pio_cmds = 0;
-
-	/* Required functions */
-	esp->dma_bytes_sent = &dma_bytes_sent;
-	esp->dma_can_transfer = &dma_can_transfer;
-	esp->dma_dump_state = &dma_dump_state;
-	esp->dma_init_read = &dma_init_read;
-	esp->dma_init_write = &dma_init_write;
-	esp->dma_ints_off = &dma_ints_off;
-	esp->dma_ints_on = &dma_ints_on;
-	esp->dma_irq_p = &dma_irq_p;
-	esp->dma_ports_p = &dma_ports_p;
-	esp->dma_setup = &dma_setup;
-
-	/* Optional functions */
-	esp->dma_barrier = &dma_barrier;
-	esp->dma_invalidate = &dma_invalidate;
-	esp->dma_drain = &dma_drain;
-	esp->dma_irq_entry = 0;
-	esp->dma_irq_exit = 0;
-	esp->dma_led_on = 0;
-	esp->dma_led_off = 0;
-	esp->dma_poll = &dma_poll;
-	esp->dma_reset = &dma_reset;
-
-        /* virtual DMA functions */
-        esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
-        esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
-        esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
-        esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
-        esp->dma_advance_sg = &dma_advance_sg;
-	    
-	/* SCSI chip speed */
-	esp->cfreq = 20000000;
-	esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE);
-	esp->dregs = (void *)SUN3X_ESP_DMA;
-
-	esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE);
-	esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command);
-
-	esp->irq = 2;
-	if (request_irq(esp->irq, esp_intr, IRQF_DISABLED,
-			"SUN3X SCSI", esp->ehost)) {
-		esp_deallocate(esp);
-		return 0;
-	}
-
-	esp->scsi_id = 7;
-	esp->diff = 0;
-
-	esp_initialize(esp);
-
- 	/* for reasons beyond my knowledge (and which should likely be fixed)
- 	   sync mode doesn't work on a 3/80 at 5mhz.  but it does at 4. */
- 	esp->sync_defp = 0x3f;
-
-	printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
-	       esps_in_use);
-	esps_running = esps_in_use;
-	return esps_in_use;
+	writeb(val, esp->regs + (reg * 4UL));
 }
 
-static void dma_do_drain(struct NCR_ESP *esp)
+static u8 sun3x_esp_read8(struct esp *esp, unsigned long reg)
 {
- 	struct sparc_dma_registers *dregs =
- 		(struct sparc_dma_registers *) esp->dregs;
- 	
- 	int count = 500000;
- 
- 	while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0)) 
- 		udelay(1);
- 
- 	if(!count) {
- 		printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
- 	}
- 
- 	dregs->cond_reg |= DMA_FIFO_STDRAIN;
- 	
- 	count = 500000;
- 
- 	while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0)) 
- 		udelay(1);
- 
- 	if(!count) {
- 		printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
- 	}
- 
-}
- 
-static void dma_barrier(struct NCR_ESP *esp)
-{
-  	struct sparc_dma_registers *dregs =
-  		(struct sparc_dma_registers *) esp->dregs;
- 	int count = 500000;
-  
- 	while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0))
-  		udelay(1);
- 
- 	if(!count) {
- 		printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
- 	}
- 
-  	dregs->cond_reg &= ~(DMA_ENABLE);
+	return readb(esp->regs + (reg * 4UL));
 }
 
-/* This uses various DMA csr fields and the fifo flags count value to
- * determine how many bytes were successfully sent/received by the ESP.
- */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+static dma_addr_t sun3x_esp_map_single(struct esp *esp, void *buf,
+				      size_t sz, int dir)
 {
-	struct sparc_dma_registers *dregs = 
-		(struct sparc_dma_registers *) esp->dregs;
-
-	int rval = dregs->st_addr - esp->esp_command_dvma;
-
-	return rval - fifo_count;
+	return dma_map_single(esp->dev, buf, sz, dir);
 }
 
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+static int sun3x_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+				  int num_sg, int dir)
 {
-	return sp->SCp.this_residual;
+	return dma_map_sg(esp->dev, sg, num_sg, dir);
 }
 
-static void dma_drain(struct NCR_ESP *esp)
+static void sun3x_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+				  size_t sz, int dir)
 {
-	struct sparc_dma_registers *dregs =
-		(struct sparc_dma_registers *) esp->dregs;
-	int count = 500000;
+	dma_unmap_single(esp->dev, addr, sz, dir);
+}
 
-	if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
-		dregs->cond_reg |= DMA_FIFO_STDRAIN;
-		while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0))
-			udelay(1);
-		if(!count) {
-			printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
+static void sun3x_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+			      int num_sg, int dir)
+{
+	dma_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int sun3x_esp_irq_pending(struct esp *esp)
+{
+	if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
+		return 1;
+	return 0;
+}
+
+static void sun3x_esp_reset_dma(struct esp *esp)
+{
+	u32 val;
+
+	val = dma_read32(DMA_CSR);
+	dma_write32(val | DMA_RST_SCSI, DMA_CSR);
+	dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
+
+	/* Enable interrupts.  */
+	val = dma_read32(DMA_CSR);
+	dma_write32(val | DMA_INT_ENAB, DMA_CSR);
+}
+
+static void sun3x_esp_dma_drain(struct esp *esp)
+{
+	u32 csr;
+	int lim;
+
+	csr = dma_read32(DMA_CSR);
+	if (!(csr & DMA_FIFO_ISDRAIN))
+		return;
+
+	dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
+
+	lim = 1000;
+	while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) {
+		if (--lim == 0) {
+			printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n",
+			       esp->host->unique_id);
+			break;
 		}
-
-	}
-}
-
-static void dma_invalidate(struct NCR_ESP *esp)
-{
-	struct sparc_dma_registers *dregs =
-		(struct sparc_dma_registers *) esp->dregs;
-
-	__u32 tmp;
-	int count = 500000;
-
-	while(((tmp = dregs->cond_reg) & DMA_PEND_READ) && (--count > 0)) 
 		udelay(1);
-
-	if(!count) {
-		printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg);
 	}
-
-	dregs->cond_reg = tmp | DMA_FIFO_INV;
-	dregs->cond_reg &= ~DMA_FIFO_INV;
-
 }
 
-static void dma_dump_state(struct NCR_ESP *esp)
+static void sun3x_esp_dma_invalidate(struct esp *esp)
 {
-	struct sparc_dma_registers *dregs =
-		(struct sparc_dma_registers *) esp->dregs;
+	u32 val;
+	int lim;
 
-	ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%08lx>\n",
-		esp->esp_id, dregs->cond_reg, dregs->st_addr));
-}
-
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
-{
-	struct sparc_dma_registers *dregs = 
-		(struct sparc_dma_registers *) esp->dregs;
-
-	dregs->st_addr = vaddress;
-	dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
-}
-
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
-{
-	struct sparc_dma_registers *dregs = 
-		(struct sparc_dma_registers *) esp->dregs;
-
-	/* Set up the DMA counters */
-
-	dregs->st_addr = vaddress;
-	dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
-}
-
-static void dma_ints_off(struct NCR_ESP *esp)
-{
-	DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs);
-}
-
-static void dma_ints_on(struct NCR_ESP *esp)
-{
-	DMA_INTSON((struct sparc_dma_registers *) esp->dregs);
-}
-
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-	return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs);
-}
-
-static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr)
-{
-	int count = 50;
-	dma_do_drain(esp);
-
-	/* Wait till the first bits settle. */
-	while((*(volatile unsigned char *)vaddr == 0xff) && (--count > 0))
+	lim = 1000;
+	while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) {
+		if (--lim == 0) {
+			printk(KERN_ALERT PFX "esp%d: DMA will not "
+			       "invalidate!\n", esp->host->unique_id);
+			break;
+		}
 		udelay(1);
-
-	if(!count) {
-//		printk("%s:%d timeout expire (data %02x)\n", __FILE__, __LINE__,
-//		       esp_read(esp->eregs->esp_fdata));
-		//mach_halt();
-		vaddr[0] = esp_read(esp->eregs->esp_fdata);
-		vaddr[1] = esp_read(esp->eregs->esp_fdata);
 	}
 
-}	
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-	return (((struct sparc_dma_registers *) esp->dregs)->cond_reg 
-			& DMA_INT_ENAB);
+	val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
+	val |= DMA_FIFO_INV;
+	dma_write32(val, DMA_CSR);
+	val &= ~DMA_FIFO_INV;
+	dma_write32(val, DMA_CSR);
 }
 
-/* Resetting various pieces of the ESP scsi driver chipset/buses. */
-static void dma_reset(struct NCR_ESP *esp)
+static void sun3x_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+				  u32 dma_count, int write, u8 cmd)
 {
-	struct sparc_dma_registers *dregs =
-		(struct sparc_dma_registers *)esp->dregs;
+	u32 csr;
 
-	/* Punt the DVMA into a known state. */
-	dregs->cond_reg |= DMA_RST_SCSI;
-	dregs->cond_reg &= ~(DMA_RST_SCSI);
-	DMA_INTSON(dregs);
+	BUG_ON(!(cmd & ESP_CMD_DMA));
+
+	sun3x_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+	sun3x_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+	csr = dma_read32(DMA_CSR);
+	csr |= DMA_ENABLE;
+	if (write)
+		csr |= DMA_ST_WRITE;
+	else
+		csr &= ~DMA_ST_WRITE;
+	dma_write32(csr, DMA_CSR);
+	dma_write32(addr, DMA_ADDR);
+
+	scsi_esp_cmd(esp, cmd);
 }
 
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+static int sun3x_esp_dma_error(struct esp *esp)
 {
-	struct sparc_dma_registers *dregs = 
-		(struct sparc_dma_registers *) esp->dregs;
-	unsigned long nreg = dregs->cond_reg;
+	u32 csr = dma_read32(DMA_CSR);
 
-//	printk("dma_setup %c addr %08x cnt %08x\n",
-//	       write ? 'W' : 'R', addr, count);
+	if (csr & DMA_HNDL_ERROR)
+		return 1;
 
-	dma_do_drain(esp);
-
-	if(write)
-		nreg |= DMA_ST_WRITE;
-	else {
-		nreg &= ~(DMA_ST_WRITE);
-	}
-		
-	nreg |= DMA_ENABLE;
-	dregs->cond_reg = nreg;
-	dregs->st_addr = addr;
+	return 0;
 }
 
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-    sp->SCp.have_data_in = dvma_map((unsigned long)sp->SCp.buffer,
-				       sp->SCp.this_residual);
-    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
-}
-
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-    int sz = sp->SCp.buffers_residual;
-    struct scatterlist *sg = sp->SCp.buffer;
-
-    while (sz >= 0) {
-	    sg[sz].dma_address = dvma_map((unsigned long)sg_virt(&sg[sz]),
-					  sg[sz].length);
-	    sz--;
-    }
-    sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address);
-}
-
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-    dvma_unmap((char *)sp->SCp.have_data_in);
-}
-
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
-{
-    int sz = sp->use_sg - 1;
-    struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
-                        
-    while(sz >= 0) {
-        dvma_unmap((char *)sg[sz].dma_address);
-        sz--;
-    }
-}
-
-static void dma_advance_sg (Scsi_Cmnd *sp)
-{
-    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address);
-}
-
-static int sun3x_esp_release(struct Scsi_Host *instance)
-{
-	/* this code does not support being compiled as a module */	 
-	return 1;
-
-}
-
-static struct scsi_host_template driver_template = {
-	.proc_name		= "sun3x_esp",
-	.proc_info		= &esp_proc_info,
-	.name			= "Sun ESP 100/100a/200",
-	.detect			= sun3x_esp_detect,
-	.release                = sun3x_esp_release,
-	.slave_alloc		= esp_slave_alloc,
-	.slave_destroy		= esp_slave_destroy,
-	.info			= esp_info,
-	.queuecommand		= esp_queue,
-	.eh_abort_handler	= esp_abort,
-	.eh_bus_reset_handler	= esp_reset,
-	.can_queue		= 7,
-	.this_id		= 7,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= DISABLE_CLUSTERING,
+static const struct esp_driver_ops sun3x_esp_ops = {
+	.esp_write8	=	sun3x_esp_write8,
+	.esp_read8	=	sun3x_esp_read8,
+	.map_single	=	sun3x_esp_map_single,
+	.map_sg		=	sun3x_esp_map_sg,
+	.unmap_single	=	sun3x_esp_unmap_single,
+	.unmap_sg	=	sun3x_esp_unmap_sg,
+	.irq_pending	=	sun3x_esp_irq_pending,
+	.reset_dma	=	sun3x_esp_reset_dma,
+	.dma_drain	=	sun3x_esp_dma_drain,
+	.dma_invalidate	=	sun3x_esp_dma_invalidate,
+	.send_dma_cmd	=	sun3x_esp_send_dma_cmd,
+	.dma_error	=	sun3x_esp_dma_error,
 };
 
+static int __devinit esp_sun3x_probe(struct platform_device *dev)
+{
+	struct scsi_host_template *tpnt = &scsi_esp_template;
+	struct Scsi_Host *host;
+	struct esp *esp;
+	struct resource *res;
+	int err = -ENOMEM;
 
-#include "scsi_module.c"
+	host = scsi_host_alloc(tpnt, sizeof(struct esp));
+	if (!host)
+		goto fail;
 
+	host->max_id = 8;
+	esp = shost_priv(host);
+
+	esp->host = host;
+	esp->dev = dev;
+	esp->ops = &sun3x_esp_ops;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res && !res->start)
+		goto fail_unlink;
+
+	esp->regs = ioremap_nocache(res->start, 0x20);
+	if (!esp->regs)
+		goto fail_unmap_regs;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	if (!res && !res->start)
+		goto fail_unmap_regs;
+
+	esp->dma_regs = ioremap_nocache(res->start, 0x10);
+
+	esp->command_block = dma_alloc_coherent(esp->dev, 16,
+						&esp->command_block_dma,
+						GFP_KERNEL);
+	if (!esp->command_block)
+		goto fail_unmap_regs_dma;
+
+	host->irq = platform_get_irq(dev, 0);
+	err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED,
+			  "SUN3X ESP", esp);
+	if (err < 0)
+		goto fail_unmap_command_block;
+
+	esp->scsi_id = 7;
+	esp->host->this_id = esp->scsi_id;
+	esp->scsi_id_mask = (1 << esp->scsi_id);
+	esp->cfreq = 20000000;
+
+	dev_set_drvdata(&dev->dev, esp);
+
+	err = scsi_esp_register(esp, &dev->dev);
+	if (err)
+		goto fail_free_irq;
+
+	return 0;
+
+fail_free_irq:
+	free_irq(host->irq, esp);
+fail_unmap_command_block:
+	dma_free_coherent(esp->dev, 16,
+			  esp->command_block,
+			  esp->command_block_dma);
+fail_unmap_regs_dma:
+	iounmap(esp->dma_regs);
+fail_unmap_regs:
+	iounmap(esp->regs);
+fail_unlink:
+	scsi_host_put(host);
+fail:
+	return err;
+}
+
+static int __devexit esp_sun3x_remove(struct platform_device *dev)
+{
+	struct esp *esp = dev_get_drvdata(&dev->dev);
+	unsigned int irq = esp->host->irq;
+	u32 val;
+
+	scsi_esp_unregister(esp);
+
+	/* Disable interrupts.  */
+	val = dma_read32(DMA_CSR);
+	dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
+
+	free_irq(irq, esp);
+	dma_free_coherent(esp->dev, 16,
+			  esp->command_block,
+			  esp->command_block_dma);
+
+	scsi_host_put(esp->host);
+
+	return 0;
+}
+
+static struct platform_driver esp_sun3x_driver = {
+	.probe          = esp_sun3x_probe,
+	.remove         = __devexit_p(esp_sun3x_remove),
+	.driver = {
+		.name   = "sun3x_esp",
+	},
+};
+
+static int __init sun3x_esp_init(void)
+{
+	return platform_driver_register(&esp_sun3x_driver);
+}
+
+static void __exit sun3x_esp_exit(void)
+{
+	platform_driver_unregister(&esp_sun3x_driver);
+}
+
+MODULE_DESCRIPTION("Sun3x ESP SCSI driver");
+MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(sun3x_esp_init);
+module_exit(sun3x_esp_exit);
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 254bdae..35142b5 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -3842,7 +3842,7 @@
 	if (cp->startp == cp->phys.head.lastp ||
 	    sym_evaluate_dp(np, cp, scr_to_cpu(cp->phys.head.lastp),
 			    &dp_ofs) < 0) {
-		return cp->data_len;
+		return cp->data_len - cp->odd_byte_adjustment;
 	}
 
 	/*
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index 662c004..58d7eee 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1216,7 +1216,7 @@
       cpp->xdir = DTD_IN;
       return;
       }
-   else if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
+   else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
       cpp->xdir = DTD_OUT;
       return;
       }
diff --git a/fs/Kconfig b/fs/Kconfig
index 3bf6ace..d731282 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1778,12 +1778,9 @@
 	tristate
 
 config SUNRPC_XPRT_RDMA
-	tristate "RDMA transport for sunrpc (EXPERIMENTAL)"
+	tristate
 	depends on SUNRPC && INFINIBAND && EXPERIMENTAL
-	default m
-	help
-	  Adds a client RPC transport for supporting kernel NFS over RDMA
-	  mounts, including Infiniband and iWARP. Experimental.
+	default SUNRPC && INFINIBAND
 
 config SUNRPC_BIND34
 	bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b144b19..f55c437 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -697,6 +697,17 @@
 }
 
 /*
+ * If the page cache is marked as unsafe or invalid, then we can't rely on
+ * the PageUptodate() flag. In this case, we will need to turn off
+ * write optimisations that depend on the page contents being correct.
+ */
+static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
+{
+	return PageUptodate(page) &&
+		!(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA));
+}
+
+/*
  * Update and possibly write a cached page of an NFS file.
  *
  * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad
@@ -717,10 +728,13 @@
 		(long long)(page_offset(page) +offset));
 
 	/* If we're not using byte range locks, and we know the page
-	 * is entirely in cache, it may be more efficient to avoid
-	 * fragmenting write requests.
+	 * is up to date, it may be more efficient to extend the write
+	 * to cover the entire page in order to avoid fragmentation
+	 * inefficiencies.
 	 */
-	if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
+	if (nfs_write_pageuptodate(page, inode) &&
+			inode->i_flock == NULL &&
+			!(file->f_mode & O_SYNC)) {
 		count = max(count + offset, nfs_page_length(page));
 		offset = 0;
 	}
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index d1491aa..9731645 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -70,7 +70,6 @@
 				   xfs_iget.o \
 				   xfs_inode.o \
 				   xfs_inode_item.o \
-				   xfs_iocore.o \
 				   xfs_iomap.o \
 				   xfs_itable.o \
 				   xfs_dfrag.o \
diff --git a/fs/xfs/linux-2.6/spin.h b/fs/xfs/linux-2.6/spin.h
deleted file mode 100644
index 50a6191..0000000
--- a/fs/xfs/linux-2.6/spin.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_SUPPORT_SPIN_H__
-#define __XFS_SUPPORT_SPIN_H__
-
-#include <linux/sched.h>	/* preempt needs this */
-#include <linux/spinlock.h>
-
-/*
- * Map lock_t from IRIX to Linux spinlocks.
- *
- * We do not make use of lock_t from interrupt context, so we do not
- * have to worry about disabling interrupts at all (unlike IRIX).
- */
-
-typedef spinlock_t lock_t;
-
-#define SPLDECL(s)			unsigned long s
-#ifndef DEFINE_SPINLOCK
-#define DEFINE_SPINLOCK(s)		spinlock_t s = SPIN_LOCK_UNLOCKED
-#endif
-
-#define spinlock_init(lock, name)	spin_lock_init(lock)
-#define	spinlock_destroy(lock)
-#define mutex_spinlock(lock)		({ spin_lock(lock); 0; })
-#define mutex_spinunlock(lock, s)	do { spin_unlock(lock); (void)s; } while (0)
-#define nested_spinlock(lock)		spin_lock(lock)
-#define nested_spinunlock(lock)		spin_unlock(lock)
-
-#endif /* __XFS_SUPPORT_SPIN_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 2e34b10..e051952 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -107,6 +107,18 @@
 #define xfs_page_trace(tag, inode, page, pgoff)
 #endif
 
+STATIC struct block_device *
+xfs_find_bdev_for_inode(
+	struct xfs_inode	*ip)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+
+	if (XFS_IS_REALTIME_INODE(ip))
+		return mp->m_rtdev_targp->bt_bdev;
+	else
+		return mp->m_ddev_targp->bt_bdev;
+}
+
 /*
  * Schedule IO completion handling on a xfsdatad if this was
  * the final hold on this ioend. If we are asked to wait,
@@ -151,7 +163,7 @@
 /*
  * Update on-disk file size now that data has been written to disk.
  * The current in-memory file size is i_size.  If a write is beyond
- * eof io_new_size will be the intended file size until i_size is
+ * eof i_new_size will be the intended file size until i_size is
  * updated.  If this write does not extend all the way to the valid
  * file size then restrict this update to the end of the write.
  */
@@ -173,7 +185,7 @@
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 
-	isize = MAX(ip->i_size, ip->i_iocore.io_new_size);
+	isize = MAX(ip->i_size, ip->i_new_size);
 	isize = MIN(isize, bsize);
 
 	if (ip->i_d.di_size < isize) {
@@ -226,12 +238,13 @@
 {
 	xfs_ioend_t		*ioend =
 		container_of(work, xfs_ioend_t, io_work);
+	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
 	xfs_off_t		offset = ioend->io_offset;
 	size_t			size = ioend->io_size;
 
 	if (likely(!ioend->io_error)) {
-		xfs_bmap(XFS_I(ioend->io_inode), offset, size,
-				BMAPI_UNWRITTEN, NULL, NULL);
+		if (!XFS_FORCED_SHUTDOWN(ip->i_mount))
+			xfs_iomap_write_unwritten(ip, offset, size);
 		xfs_setfilesize(ioend);
 	}
 	xfs_destroy_ioend(ioend);
@@ -304,7 +317,7 @@
 	xfs_inode_t		*ip = XFS_I(inode);
 	int			error, nmaps = 1;
 
-	error = xfs_bmap(ip, offset, count,
+	error = xfs_iomap(ip, offset, count,
 				flags, mapp, &nmaps);
 	if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
 		xfs_iflags_set(ip, XFS_IMODIFIED);
@@ -1323,7 +1336,7 @@
 	offset = (xfs_off_t)iblock << inode->i_blkbits;
 	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
 	size = bh_result->b_size;
-	error = xfs_bmap(XFS_I(inode), offset, size,
+	error = xfs_iomap(XFS_I(inode), offset, size,
 			     create ? flags : BMAPI_READ, &iomap, &niomap);
 	if (error)
 		return -error;
@@ -1471,28 +1484,21 @@
 {
 	struct file	*file = iocb->ki_filp;
 	struct inode	*inode = file->f_mapping->host;
-	xfs_iomap_t	iomap;
-	int		maps = 1;
-	int		error;
+	struct block_device *bdev;
 	ssize_t		ret;
 
-	error = xfs_bmap(XFS_I(inode), offset, 0,
-				BMAPI_DEVICE, &iomap, &maps);
-	if (error)
-		return -error;
+	bdev = xfs_find_bdev_for_inode(XFS_I(inode));
 
 	if (rw == WRITE) {
 		iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
 		ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
-			iomap.iomap_target->bt_bdev,
-			iov, offset, nr_segs,
+			bdev, iov, offset, nr_segs,
 			xfs_get_blocks_direct,
 			xfs_end_io_direct);
 	} else {
 		iocb->private = xfs_alloc_ioend(inode, IOMAP_READ);
 		ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
-			iomap.iomap_target->bt_bdev,
-			iov, offset, nr_segs,
+			bdev, iov, offset, nr_segs,
 			xfs_get_blocks_direct,
 			xfs_end_io_direct);
 	}
@@ -1525,8 +1531,7 @@
 	struct inode		*inode = (struct inode *)mapping->host;
 	struct xfs_inode	*ip = XFS_I(inode);
 
-	vn_trace_entry(XFS_I(inode), __FUNCTION__,
-			(inst_t *)__return_address);
+	xfs_itrace_entry(XFS_I(inode));
 	xfs_rwlock(ip, VRWLOCK_READ);
 	xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
 	xfs_rwunlock(ip, VRWLOCK_READ);
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 0382c19..e347bfd 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -387,8 +387,6 @@
 		if (unlikely(page == NULL)) {
 			if (flags & XBF_READ_AHEAD) {
 				bp->b_page_count = i;
-				for (i = 0; i < bp->b_page_count; i++)
-					unlock_page(bp->b_pages[i]);
 				return -ENOMEM;
 			}
 
@@ -418,24 +416,17 @@
 		ASSERT(!PagePrivate(page));
 		if (!PageUptodate(page)) {
 			page_count--;
-			if (blocksize >= PAGE_CACHE_SIZE) {
-				if (flags & XBF_READ)
-					bp->b_locked = 1;
-			} else if (!PagePrivate(page)) {
+			if (blocksize < PAGE_CACHE_SIZE && !PagePrivate(page)) {
 				if (test_page_region(page, offset, nbytes))
 					page_count++;
 			}
 		}
 
+		unlock_page(page);
 		bp->b_pages[i] = page;
 		offset = 0;
 	}
 
-	if (!bp->b_locked) {
-		for (i = 0; i < bp->b_page_count; i++)
-			unlock_page(bp->b_pages[i]);
-	}
-
 	if (page_count == bp->b_page_count)
 		bp->b_flags |= XBF_DONE;
 
@@ -751,7 +742,6 @@
 		bp->b_pages[i] = mem_to_page((void *)pageaddr);
 		pageaddr += PAGE_CACHE_SIZE;
 	}
-	bp->b_locked = 0;
 
 	bp->b_count_desired = len;
 	bp->b_buffer_length = buflen;
@@ -1098,25 +1088,13 @@
 	return status;
 }
 
-STATIC_INLINE int
-_xfs_buf_iolocked(
-	xfs_buf_t		*bp)
-{
-	ASSERT(bp->b_flags & (XBF_READ | XBF_WRITE));
-	if (bp->b_flags & XBF_READ)
-		return bp->b_locked;
-	return 0;
-}
-
 STATIC_INLINE void
 _xfs_buf_ioend(
 	xfs_buf_t		*bp,
 	int			schedule)
 {
-	if (atomic_dec_and_test(&bp->b_io_remaining) == 1) {
-		bp->b_locked = 0;
+	if (atomic_dec_and_test(&bp->b_io_remaining) == 1)
 		xfs_buf_ioend(bp, schedule);
-	}
 }
 
 STATIC void
@@ -1147,10 +1125,6 @@
 
 		if (--bvec >= bio->bi_io_vec)
 			prefetchw(&bvec->bv_page->flags);
-
-		if (_xfs_buf_iolocked(bp)) {
-			unlock_page(page);
-		}
 	} while (bvec >= bio->bi_io_vec);
 
 	_xfs_buf_ioend(bp, 1);
@@ -1161,13 +1135,12 @@
 _xfs_buf_ioapply(
 	xfs_buf_t		*bp)
 {
-	int			i, rw, map_i, total_nr_pages, nr_pages;
+	int			rw, map_i, total_nr_pages, nr_pages;
 	struct bio		*bio;
 	int			offset = bp->b_offset;
 	int			size = bp->b_count_desired;
 	sector_t		sector = bp->b_bn;
 	unsigned int		blocksize = bp->b_target->bt_bsize;
-	int			locking = _xfs_buf_iolocked(bp);
 
 	total_nr_pages = bp->b_page_count;
 	map_i = 0;
@@ -1190,7 +1163,7 @@
 	 * filesystem block size is not smaller than the page size.
 	 */
 	if ((bp->b_buffer_length < PAGE_CACHE_SIZE) &&
-	    (bp->b_flags & XBF_READ) && locking &&
+	    (bp->b_flags & XBF_READ) &&
 	    (blocksize >= PAGE_CACHE_SIZE)) {
 		bio = bio_alloc(GFP_NOIO, 1);
 
@@ -1207,24 +1180,6 @@
 		goto submit_io;
 	}
 
-	/* Lock down the pages which we need to for the request */
-	if (locking && (bp->b_flags & XBF_WRITE) && (bp->b_locked == 0)) {
-		for (i = 0; size; i++) {
-			int		nbytes = PAGE_CACHE_SIZE - offset;
-			struct page	*page = bp->b_pages[i];
-
-			if (nbytes > size)
-				nbytes = size;
-
-			lock_page(page);
-
-			size -= nbytes;
-			offset = 0;
-		}
-		offset = bp->b_offset;
-		size = bp->b_count_desired;
-	}
-
 next_chunk:
 	atomic_inc(&bp->b_io_remaining);
 	nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT);
@@ -1571,7 +1526,7 @@
 
 	INIT_LIST_HEAD(&btp->bt_list);
 	INIT_LIST_HEAD(&btp->bt_delwrite_queue);
-	spinlock_init(&btp->bt_delwrite_lock, "delwri_lock");
+	spin_lock_init(&btp->bt_delwrite_lock);
 	btp->bt_flags = 0;
 	btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd");
 	if (IS_ERR(btp->bt_task)) {
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index b5908a3..a3d207d 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -143,7 +143,6 @@
 	void			*b_fspriv2;
 	void			*b_fspriv3;
 	unsigned short		b_error;	/* error code on I/O */
-	unsigned short		b_locked;	/* page array is locked */
 	unsigned int		b_page_count;	/* size of page array */
 	unsigned int		b_offset;	/* page offset in first page */
 	struct page		**b_pages;	/* array of page pointers */
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 15bd494..ca4f66c 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -118,20 +118,29 @@
 	u64			ino,
 	u32			generation)
  {
-	xfs_fid_t		xfid;
-	bhv_vnode_t		*vp;
+ 	xfs_mount_t		*mp = XFS_M(sb);
+	xfs_inode_t		*ip;
 	int			error;
 
-	xfid.fid_len = sizeof(xfs_fid_t) - sizeof(xfid.fid_len);
-	xfid.fid_pad = 0;
-	xfid.fid_ino = ino;
-	xfid.fid_gen = generation;
+	/*
+	 * NFS can sometimes send requests for ino 0.  Fail them gracefully.
+	 */
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
 
-	error = xfs_vget(XFS_M(sb), &vp, &xfid);
+	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
 	if (error)
 		return ERR_PTR(-error);
+	if (!ip)
+		return ERR_PTR(-EIO);
 
-	return vp ? vn_to_inode(vp) : NULL;
+	if (!ip->i_d.di_mode || ip->i_d.di_gen != generation) {
+		xfs_iput_new(ip, XFS_ILOCK_SHARED);
+		return ERR_PTR(-ENOENT);
+	}
+
+	xfs_iunlock(ip, XFS_ILOCK_SHARED);
+	return ip->i_vnode;
 }
 
 STATIC struct dentry *
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 21a1c2b..edab1ff 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -350,8 +350,8 @@
 
 		size = buf.used;
 		de = (struct hack_dirent *)buf.dirent;
-		curr_offset = de->offset /* & 0x7fffffff */;
 		while (size > 0) {
+			curr_offset = de->offset /* & 0x7fffffff */;
 			if (filldir(dirent, de->name, de->namlen,
 					curr_offset & 0x7fffffff,
 					de->ino, de->d_type)) {
@@ -362,7 +362,6 @@
 				       sizeof(u64));
 			size -= reclen;
 			de = (struct hack_dirent *)((char *)de + reclen);
-			curr_offset = de->offset /* & 0x7fffffff */;
 		}
 	}
 
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 9febf9d..ef90e64 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -47,5 +47,6 @@
 /*
  * Global system credential structure.
  */
-cred_t sys_cred_val, *sys_cred = &sys_cred_val;
+static cred_t sys_cred_val;
+cred_t *sys_cred = &sys_cred_val;
 
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 98a5656..4c82a05 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -75,7 +75,6 @@
 	xfs_handle_t		handle;
 	xfs_fsop_handlereq_t	hreq;
 	struct inode		*inode;
-	bhv_vnode_t		*vp;
 
 	if (copy_from_user(&hreq, arg, sizeof(hreq)))
 		return -XFS_ERROR(EFAULT);
@@ -134,21 +133,16 @@
 		return -XFS_ERROR(EBADF);
 	}
 
-	/* we need the vnode */
-	vp = vn_from_inode(inode);
-
 	/* now we can grab the fsid */
 	memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
 			sizeof(xfs_fsid_t));
 	hsize = sizeof(xfs_fsid_t);
 
 	if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
-		xfs_inode_t	*ip;
+		xfs_inode_t	*ip = XFS_I(inode);
 		int		lock_mode;
 
 		/* need to get access to the xfs_inode to read the generation */
-		ip = xfs_vtoi(vp);
-		ASSERT(ip);
 		lock_mode = xfs_ilock_map_shared(ip);
 
 		/* fill in fid section of handle from inode */
@@ -176,21 +170,19 @@
 
 
 /*
- * Convert userspace handle data into vnode (and inode).
- * We [ab]use the fact that all the fsop_handlereq ioctl calls
- * have a data structure argument whose first component is always
- * a xfs_fsop_handlereq_t, so we can cast to and from this type.
- * This allows us to optimise the copy_from_user calls and gives
- * a handy, shared routine.
+ * Convert userspace handle data into inode.
  *
- * If no error, caller must always VN_RELE the returned vp.
+ * We use the fact that all the fsop_handlereq ioctl calls have a data
+ * structure argument whose first component is always a xfs_fsop_handlereq_t,
+ * so we can pass that sub structure into this handy, shared routine.
+ *
+ * If no error, caller must always iput the returned inode.
  */
 STATIC int
 xfs_vget_fsop_handlereq(
 	xfs_mount_t		*mp,
 	struct inode		*parinode,	/* parent inode pointer    */
 	xfs_fsop_handlereq_t	*hreq,
-	bhv_vnode_t		**vp,
 	struct inode		**inode)
 {
 	void			__user *hanp;
@@ -199,8 +191,6 @@
 	xfs_handle_t		*handlep;
 	xfs_handle_t		handle;
 	xfs_inode_t		*ip;
-	struct inode		*inodep;
-	bhv_vnode_t		*vpp;
 	xfs_ino_t		ino;
 	__u32			igen;
 	int			error;
@@ -241,7 +231,7 @@
 	}
 
 	/*
-	 * Get the XFS inode, building a vnode to go with it.
+	 * Get the XFS inode, building a Linux inode to go with it.
 	 */
 	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
 	if (error)
@@ -253,12 +243,9 @@
 		return XFS_ERROR(ENOENT);
 	}
 
-	vpp = XFS_ITOV(ip);
-	inodep = vn_to_inode(vpp);
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
-	*vp = vpp;
-	*inode = inodep;
+	*inode = XFS_ITOV(ip);
 	return 0;
 }
 
@@ -275,7 +262,6 @@
 	struct file		*filp;
 	struct inode		*inode;
 	struct dentry		*dentry;
-	bhv_vnode_t		*vp;
 	xfs_fsop_handlereq_t	hreq;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -283,7 +269,7 @@
 	if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
 		return -XFS_ERROR(EFAULT);
 
-	error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
+	error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode);
 	if (error)
 		return -error;
 
@@ -385,7 +371,6 @@
 {
 	struct inode		*inode;
 	xfs_fsop_handlereq_t	hreq;
-	bhv_vnode_t		*vp;
 	__u32			olen;
 	void			*link;
 	int			error;
@@ -395,7 +380,7 @@
 	if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
 		return -XFS_ERROR(EFAULT);
 
-	error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
+	error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode);
 	if (error)
 		return -error;
 
@@ -438,34 +423,32 @@
 	struct fsdmidata	fsd;
 	xfs_fsop_setdm_handlereq_t dmhreq;
 	struct inode		*inode;
-	bhv_vnode_t		*vp;
 
 	if (!capable(CAP_MKNOD))
 		return -XFS_ERROR(EPERM);
 	if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
 		return -XFS_ERROR(EFAULT);
 
-	error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &vp, &inode);
+	error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &inode);
 	if (error)
 		return -error;
 
 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
-		VN_RELE(vp);
-		return -XFS_ERROR(EPERM);
+		error = -XFS_ERROR(EPERM);
+		goto out;
 	}
 
 	if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
-		VN_RELE(vp);
-		return -XFS_ERROR(EFAULT);
+		error = -XFS_ERROR(EFAULT);
+		goto out;
 	}
 
-	error = xfs_set_dmattrs(xfs_vtoi(vp),
-			fsd.fsd_dmevmask, fsd.fsd_dmstate);
+	error = -xfs_set_dmattrs(XFS_I(inode), fsd.fsd_dmevmask,
+				 fsd.fsd_dmstate);
 
-	VN_RELE(vp);
-	if (error)
-		return -error;
-	return 0;
+ out:
+	iput(inode);
+	return error;
 }
 
 STATIC int
@@ -478,7 +461,6 @@
 	attrlist_cursor_kern_t	*cursor;
 	xfs_fsop_attrlist_handlereq_t al_hreq;
 	struct inode		*inode;
-	bhv_vnode_t		*vp;
 	char			*kbuf;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -488,8 +470,7 @@
 	if (al_hreq.buflen > XATTR_LIST_MAX)
 		return -XFS_ERROR(EINVAL);
 
-	error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq,
-			&vp, &inode);
+	error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq, &inode);
 	if (error)
 		goto out;
 
@@ -509,7 +490,7 @@
  out_kfree:
 	kfree(kbuf);
  out_vn_rele:
-	VN_RELE(vp);
+	iput(inode);
  out:
 	return -error;
 }
@@ -531,7 +512,7 @@
 	if (!kbuf)
 		return ENOMEM;
 
-	error = xfs_attr_get(XFS_I(inode), name, kbuf, len, flags, NULL);
+	error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags, NULL);
 	if (error)
 		goto out_kfree;
 
@@ -598,7 +579,6 @@
 	xfs_attr_multiop_t	*ops;
 	xfs_fsop_attrmulti_handlereq_t am_hreq;
 	struct inode		*inode;
-	bhv_vnode_t		*vp;
 	unsigned int		i, size;
 	char			*attr_name;
 
@@ -607,7 +587,7 @@
 	if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
 		return -XFS_ERROR(EFAULT);
 
-	error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &vp, &inode);
+	error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &inode);
 	if (error)
 		goto out;
 
@@ -666,7 +646,7 @@
  out_kfree_ops:
 	kfree(ops);
  out_vn_rele:
-	VN_RELE(vp);
+	iput(inode);
  out:
 	return -error;
 }
@@ -702,7 +682,6 @@
 
 STATIC int
 xfs_ioc_xattr(
-	bhv_vnode_t		*vp,
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
@@ -735,12 +714,10 @@
 	void			__user *arg)
 {
 	struct inode		*inode = filp->f_path.dentry->d_inode;
-	bhv_vnode_t		*vp = vn_from_inode(inode);
 	xfs_mount_t		*mp = ip->i_mount;
 	int			error;
 
-	vn_trace_entry(XFS_I(inode), "xfs_ioctl", (inst_t *)__return_address);
-
+	xfs_itrace_entry(XFS_I(inode));
 	switch (cmd) {
 
 	case XFS_IOC_ALLOCSP:
@@ -764,7 +741,7 @@
 	case XFS_IOC_DIOINFO: {
 		struct dioattr	da;
 		xfs_buftarg_t	*target =
-			(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
+			XFS_IS_REALTIME_INODE(ip) ?
 			mp->m_rtdev_targp : mp->m_ddev_targp;
 
 		da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
@@ -796,7 +773,7 @@
 	case XFS_IOC_GETXFLAGS:
 	case XFS_IOC_SETXFLAGS:
 	case XFS_IOC_FSSETXATTR:
-		return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
+		return xfs_ioc_xattr(ip, filp, cmd, arg);
 
 	case XFS_IOC_FSSETDM: {
 		struct fsdmidata	dmi;
@@ -1203,7 +1180,6 @@
 
 STATIC int
 xfs_ioc_xattr(
-	bhv_vnode_t		*vp,
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
@@ -1237,7 +1213,7 @@
 
 		error = xfs_setattr(ip, vattr, attr_flags, NULL);
 		if (likely(!error))
-			__vn_revalidate(vp, vattr);	/* update flags */
+			vn_revalidate(XFS_ITOV(ip));	/* update flags */
 		error = -error;
 		break;
 	}
@@ -1272,7 +1248,7 @@
 
 		error = xfs_setattr(ip, vattr, attr_flags, NULL);
 		if (likely(!error))
-			__vn_revalidate(vp, vattr);	/* update flags */
+			vn_revalidate(XFS_ITOV(ip));	/* update flags */
 		error = -error;
 		break;
 	}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index bf2a956..a4b254e 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -44,6 +44,7 @@
 #include "xfs_error.h"
 #include "xfs_dfrag.h"
 #include "xfs_vnodeops.h"
+#include "xfs_ioctl32.h"
 
 #define  _NATIVE_IOC(cmd, type) \
 	  _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
@@ -379,9 +380,6 @@
 	switch (cmd) {
 	case XFS_IOC_DIOINFO:
 	case XFS_IOC_FSGEOMETRY:
-	case XFS_IOC_GETVERSION:
-	case XFS_IOC_GETXFLAGS:
-	case XFS_IOC_SETXFLAGS:
 	case XFS_IOC_FSGETXATTR:
 	case XFS_IOC_FSSETXATTR:
 	case XFS_IOC_FSGETXATTRA:
@@ -407,6 +405,11 @@
 	case XFS_IOC_ERROR_CLEARALL:
 		break;
 
+	case XFS_IOC32_GETXFLAGS:
+	case XFS_IOC32_SETXFLAGS:
+	case XFS_IOC32_GETVERSION:
+		cmd = _NATIVE_IOC(cmd, long);
+		break;
 #ifdef BROKEN_X86_ALIGNMENT
 	/* xfs_flock_t has wrong u32 vs u64 alignment */
 	case XFS_IOC_ALLOCSP_32:
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 5e8bb7f..cc4abd3 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -52,6 +52,7 @@
 #include <linux/xattr.h>
 #include <linux/namei.h>
 #include <linux/security.h>
+#include <linux/falloc.h>
 
 /*
  * Bring the atime in the XFS inode uptodate.
@@ -71,6 +72,22 @@
 }
 
 /*
+ * If the linux inode exists, mark it dirty.
+ * Used when commiting a dirty inode into a transaction so that
+ * the inode will get written back by the linux code
+ */
+void
+xfs_mark_inode_dirty_sync(
+	xfs_inode_t	*ip)
+{
+	bhv_vnode_t	*vp;
+
+	vp = XFS_ITOV_NULL(ip);
+	if (vp)
+		mark_inode_dirty_sync(vn_to_inode(vp));
+}
+
+/*
  * Change the requested timestamp in the given inode.
  * We don't lock across timestamp updates, and we don't log them but
  * we do record the fact that there is dirty information in core.
@@ -184,10 +201,6 @@
 	struct xfs_inode	*ip = XFS_I(inode);
 	loff_t size;
 
-	inode->i_nlink = ip->i_d.di_nlink;
-	inode->i_blocks =
-		XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
-					   ip->i_delayed_blks);
 	/* we're under i_sem so i_size can't change under us */
 	size = XFS_ISIZE(ip);
 	if (i_size_read(inode) != size)
@@ -542,12 +555,31 @@
 
 #ifdef CONFIG_XFS_POSIX_ACL
 STATIC int
-xfs_vn_permission(
-	struct inode	*inode,
-	int		mode,
-	struct nameidata *nd)
+xfs_check_acl(
+	struct inode		*inode,
+	int			mask)
 {
-	return -xfs_access(XFS_I(inode), mode << 6, NULL);
+	struct xfs_inode	*ip = XFS_I(inode);
+	int			error;
+
+	xfs_itrace_entry(ip);
+
+	if (XFS_IFORK_Q(ip)) {
+		error = xfs_acl_iaccess(ip, mask, NULL);
+		if (error != -1)
+			return -error;
+	}
+
+	return -EAGAIN;
+}
+
+STATIC int
+xfs_vn_permission(
+	struct inode		*inode,
+	int			mask,
+	struct nameidata	*nd)
+{
+	return generic_permission(inode, mask, xfs_check_acl);
 }
 #else
 #define xfs_vn_permission NULL
@@ -555,33 +587,61 @@
 
 STATIC int
 xfs_vn_getattr(
-	struct vfsmount	*mnt,
-	struct dentry	*dentry,
-	struct kstat	*stat)
+	struct vfsmount		*mnt,
+	struct dentry		*dentry,
+	struct kstat		*stat)
 {
-	struct inode	*inode = dentry->d_inode;
-	bhv_vattr_t	vattr = { .va_mask = XFS_AT_STAT };
-	int		error;
+	struct inode		*inode = dentry->d_inode;
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
 
-	error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY);
-	if (likely(!error)) {
-		stat->size = i_size_read(inode);
-		stat->dev = inode->i_sb->s_dev;
-		stat->rdev = (vattr.va_rdev == 0) ? 0 :
-				MKDEV(sysv_major(vattr.va_rdev) & 0x1ff,
-				      sysv_minor(vattr.va_rdev));
-		stat->mode = vattr.va_mode;
-		stat->nlink = vattr.va_nlink;
-		stat->uid = vattr.va_uid;
-		stat->gid = vattr.va_gid;
-		stat->ino = vattr.va_nodeid;
-		stat->atime = vattr.va_atime;
-		stat->mtime = vattr.va_mtime;
-		stat->ctime = vattr.va_ctime;
-		stat->blocks = vattr.va_nblocks;
-		stat->blksize = vattr.va_blocksize;
+	xfs_itrace_entry(ip);
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	stat->size = XFS_ISIZE(ip);
+	stat->dev = inode->i_sb->s_dev;
+	stat->mode = ip->i_d.di_mode;
+	stat->nlink = ip->i_d.di_nlink;
+	stat->uid = ip->i_d.di_uid;
+	stat->gid = ip->i_d.di_gid;
+	stat->ino = ip->i_ino;
+#if XFS_BIG_INUMS
+	stat->ino += mp->m_inoadd;
+#endif
+	stat->atime = inode->i_atime;
+	stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;
+	stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
+	stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;
+	stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
+	stat->blocks =
+		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
+
+
+	switch (inode->i_mode & S_IFMT) {
+	case S_IFBLK:
+	case S_IFCHR:
+		stat->blksize = BLKDEV_IOSIZE;
+		stat->rdev = MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
+				   sysv_minor(ip->i_df.if_u2.if_rdev));
+		break;
+	default:
+		if (XFS_IS_REALTIME_INODE(ip)) {
+			/*
+			 * If the file blocks are being allocated from a
+			 * realtime volume, then return the inode's realtime
+			 * extent size or the realtime volume's extent size.
+			 */
+			stat->blksize =
+				xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
+		} else
+			stat->blksize = xfs_preferred_iosize(mp);
+		stat->rdev = 0;
+		break;
 	}
-	return -error;
+
+	return 0;
 }
 
 STATIC int
@@ -636,7 +696,7 @@
 
 	error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
 	if (likely(!error))
-		__vn_revalidate(vn_from_inode(inode), &vattr);
+		vn_revalidate(vn_from_inode(inode));
 	return -error;
 }
 
@@ -750,6 +810,47 @@
 	return namesp->attr_remove(vp, attr, xflags);
 }
 
+STATIC long
+xfs_vn_fallocate(
+	struct inode	*inode,
+	int		mode,
+	loff_t		offset,
+	loff_t		len)
+{
+	long		error;
+	loff_t		new_size = 0;
+	xfs_flock64_t	bf;
+	xfs_inode_t	*ip = XFS_I(inode);
+
+	/* preallocation on directories not yet supported */
+	error = -ENODEV;
+	if (S_ISDIR(inode->i_mode))
+		goto out_error;
+
+	bf.l_whence = 0;
+	bf.l_start = offset;
+	bf.l_len = len;
+
+	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+	error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
+						0, NULL, ATTR_NOLOCK);
+	if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
+	    offset + len > i_size_read(inode))
+		new_size = offset + len;
+
+	/* Change file size if needed */
+	if (new_size) {
+		bhv_vattr_t	va;
+
+		va.va_mask = XFS_AT_SIZE;
+		va.va_size = new_size;
+		error = xfs_setattr(ip, &va, ATTR_NOLOCK, NULL);
+	}
+
+	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+out_error:
+	return error;
+}
 
 const struct inode_operations xfs_inode_operations = {
 	.permission		= xfs_vn_permission,
@@ -760,6 +861,7 @@
 	.getxattr		= xfs_vn_getxattr,
 	.listxattr		= xfs_vn_listxattr,
 	.removexattr		= xfs_vn_removexattr,
+	.fallocate		= xfs_vn_fallocate,
 };
 
 const struct inode_operations xfs_dir_inode_operations = {
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index dc3752d..3ca39c4 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -43,7 +43,6 @@
 
 #include <kmem.h>
 #include <mrlock.h>
-#include <spin.h>
 #include <sv.h>
 #include <mutex.h>
 #include <sema.h>
@@ -75,6 +74,7 @@
 #include <linux/notifier.h>
 #include <linux/delay.h>
 #include <linux/log2.h>
+#include <linux/spinlock.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
@@ -136,43 +136,19 @@
 #define current_restore_flags_nested(sp, f)	\
 		(current->flags = ((current->flags & ~(f)) | (*(sp) & (f))))
 
-#define NBPP		PAGE_SIZE
-#define NDPP		(1 << (PAGE_SHIFT - 9))
+#define spinlock_destroy(lock)
 
 #define NBBY		8		/* number of bits per byte */
-#define	NBPC		PAGE_SIZE	/* Number of bytes per click */
-#define	BPCSHIFT	PAGE_SHIFT	/* LOG2(NBPC) if exact */
 
 /*
  * Size of block device i/o is parameterized here.
  * Currently the system supports page-sized i/o.
  */
-#define	BLKDEV_IOSHIFT		BPCSHIFT
+#define	BLKDEV_IOSHIFT		PAGE_CACHE_SHIFT
 #define	BLKDEV_IOSIZE		(1<<BLKDEV_IOSHIFT)
 /* number of BB's per block device block */
 #define	BLKDEV_BB		BTOBB(BLKDEV_IOSIZE)
 
-/* bytes to clicks */
-#define	btoc(x)		(((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT)
-#define	btoct(x)	((__psunsigned_t)(x)>>BPCSHIFT)
-#define	btoc64(x)	(((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
-#define	btoct64(x)	((__uint64_t)(x)>>BPCSHIFT)
-
-/* off_t bytes to clicks */
-#define offtoc(x)       (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
-#define offtoct(x)      ((xfs_off_t)(x)>>BPCSHIFT)
-
-/* clicks to off_t bytes */
-#define	ctooff(x)	((xfs_off_t)(x)<<BPCSHIFT)
-
-/* clicks to bytes */
-#define	ctob(x)		((__psunsigned_t)(x)<<BPCSHIFT)
-#define btoct(x)        ((__psunsigned_t)(x)>>BPCSHIFT)
-#define	ctob64(x)	((__uint64_t)(x)<<BPCSHIFT)
-
-/* bytes to clicks */
-#define btoc(x)         (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT)
-
 #define ENOATTR		ENODATA		/* Attribute not found */
 #define EWRONGFS	EINVAL		/* Mount with wrong filesystem type */
 #define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
@@ -205,10 +181,6 @@
 #define xfs_stack_trace()	dump_stack()
 #define xfs_itruncate_data(ip, off)	\
 	(-vmtruncate(vn_to_inode(XFS_ITOV(ip)), (off)))
-#define xfs_statvfs_fsid(statp, mp)	\
-	({ u64 id = huge_encode_dev((mp)->m_ddev_targp->bt_dev); \
-	   __kernel_fsid_t *fsid = &(statp)->f_fsid;	\
-	(fsid->val[0] = (u32)id, fsid->val[1] = (u32)(id >> 32)); })
 
 
 /* Move the kernel do_div definition off to one side */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 6f614f3..1663533 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -58,14 +58,12 @@
 void
 xfs_rw_enter_trace(
 	int			tag,
-	xfs_iocore_t		*io,
+	xfs_inode_t		*ip,
 	void			*data,
 	size_t			segs,
 	loff_t			offset,
 	int			ioflags)
 {
-	xfs_inode_t	*ip = XFS_IO_INODE(io);
-
 	if (ip->i_rwtrace == NULL)
 		return;
 	ktrace_enter(ip->i_rwtrace,
@@ -78,8 +76,8 @@
 		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(offset & 0xffffffff)),
 		(void *)((unsigned long)ioflags),
-		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
-		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
+		(void *)((unsigned long)((ip->i_new_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_new_size & 0xffffffff)),
 		(void *)((unsigned long)current_pid()),
 		(void *)NULL,
 		(void *)NULL,
@@ -89,13 +87,12 @@
 
 void
 xfs_inval_cached_trace(
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_off_t	offset,
 	xfs_off_t	len,
 	xfs_off_t	first,
 	xfs_off_t	last)
 {
-	xfs_inode_t	*ip = XFS_IO_INODE(io);
 
 	if (ip->i_rwtrace == NULL)
 		return;
@@ -131,7 +128,7 @@
  */
 STATIC int
 xfs_iozero(
-	struct inode		*ip,	/* inode			*/
+	struct xfs_inode	*ip,	/* inode			*/
 	loff_t			pos,	/* offset in file		*/
 	size_t			count)	/* size of data to zero		*/
 {
@@ -139,7 +136,7 @@
 	struct address_space	*mapping;
 	int			status;
 
-	mapping = ip->i_mapping;
+	mapping = ip->i_vnode->i_mapping;
 	do {
 		unsigned offset, bytes;
 		void *fsdata;
@@ -205,7 +202,7 @@
 
 	if (unlikely(ioflags & IO_ISDIRECT)) {
 		xfs_buftarg_t	*target =
-			(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
+			XFS_IS_REALTIME_INODE(ip) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
 		if ((*offset & target->bt_smask) ||
 		    (size & target->bt_smask)) {
@@ -246,9 +243,8 @@
 
 	if (unlikely(ioflags & IO_ISDIRECT)) {
 		if (VN_CACHED(vp))
-			ret = xfs_flushinval_pages(ip,
-					ctooff(offtoct(*offset)),
-					-1, FI_REMAPF_LOCKED);
+			ret = xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK),
+						    -1, FI_REMAPF_LOCKED);
 		mutex_unlock(&inode->i_mutex);
 		if (ret) {
 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -256,7 +252,7 @@
 		}
 	}
 
-	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
+	xfs_rw_enter_trace(XFS_READ_ENTER, ip,
 				(void *)iovp, segs, *offset, ioflags);
 
 	iocb->ki_pos = *offset;
@@ -301,7 +297,7 @@
 			return -error;
 		}
 	}
-	xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
+	xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, ip,
 			   pipe, count, *ppos, ioflags);
 	ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
 	if (ret > 0)
@@ -323,7 +319,6 @@
 {
 	bhv_vnode_t		*vp = XFS_ITOV(ip);
 	xfs_mount_t		*mp = ip->i_mount;
-	xfs_iocore_t		*io = &ip->i_iocore;
 	ssize_t			ret;
 	struct inode		*inode = outfilp->f_mapping->host;
 	xfs_fsize_t		isize, new_size;
@@ -350,10 +345,10 @@
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	if (new_size > ip->i_size)
-		io->io_new_size = new_size;
+		ip->i_new_size = new_size;
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
-	xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
+	xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, ip,
 			   pipe, count, *ppos, ioflags);
 	ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
 	if (ret > 0)
@@ -370,9 +365,9 @@
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
 
-	if (io->io_new_size) {
+	if (ip->i_new_size) {
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		io->io_new_size = 0;
+		ip->i_new_size = 0;
 		if (ip->i_d.di_size > ip->i_size)
 			ip->i_d.di_size = ip->i_size;
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -389,20 +384,19 @@
  */
 STATIC int				/* error (positive) */
 xfs_zero_last_block(
-	struct inode	*ip,
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_fsize_t	offset,
 	xfs_fsize_t	isize)
 {
 	xfs_fileoff_t	last_fsb;
-	xfs_mount_t	*mp = io->io_mount;
+	xfs_mount_t	*mp = ip->i_mount;
 	int		nimaps;
 	int		zero_offset;
 	int		zero_len;
 	int		error = 0;
 	xfs_bmbt_irec_t	imap;
 
-	ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
+	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
 
 	zero_offset = XFS_B_FSB_OFFSET(mp, isize);
 	if (zero_offset == 0) {
@@ -415,7 +409,7 @@
 
 	last_fsb = XFS_B_TO_FSBT(mp, isize);
 	nimaps = 1;
-	error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap,
+	error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
 			  &nimaps, NULL, NULL);
 	if (error) {
 		return error;
@@ -433,14 +427,14 @@
 	 * out sync.  We need to drop the ilock while we do this so we
 	 * don't deadlock when the buffer cache calls back to us.
 	 */
-	XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
 
 	zero_len = mp->m_sb.sb_blocksize - zero_offset;
 	if (isize + zero_len > offset)
 		zero_len = offset - isize;
 	error = xfs_iozero(ip, isize, zero_len);
 
-	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
 	ASSERT(error >= 0);
 	return error;
 }
@@ -458,35 +452,33 @@
 
 int					/* error (positive) */
 xfs_zero_eof(
-	bhv_vnode_t	*vp,
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_off_t	offset,		/* starting I/O offset */
 	xfs_fsize_t	isize)		/* current inode size */
 {
-	struct inode	*ip = vn_to_inode(vp);
+	xfs_mount_t	*mp = ip->i_mount;
 	xfs_fileoff_t	start_zero_fsb;
 	xfs_fileoff_t	end_zero_fsb;
 	xfs_fileoff_t	zero_count_fsb;
 	xfs_fileoff_t	last_fsb;
 	xfs_fileoff_t	zero_off;
 	xfs_fsize_t	zero_len;
-	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		error = 0;
 	xfs_bmbt_irec_t	imap;
 
-	ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
-	ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
+	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+	ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
 	ASSERT(offset > isize);
 
 	/*
 	 * First handle zeroing the block on which isize resides.
 	 * We only zero a part of that block so it is handled specially.
 	 */
-	error = xfs_zero_last_block(ip, io, offset, isize);
+	error = xfs_zero_last_block(ip, offset, isize);
 	if (error) {
-		ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
-		ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
+		ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+		ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
 		return error;
 	}
 
@@ -514,11 +506,11 @@
 	while (start_zero_fsb <= end_zero_fsb) {
 		nimaps = 1;
 		zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
-		error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb,
+		error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
 				  0, NULL, 0, &imap, &nimaps, NULL, NULL);
 		if (error) {
-			ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
-			ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
+			ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+			ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
 			return error;
 		}
 		ASSERT(nimaps > 0);
@@ -542,7 +534,7 @@
 		 * Drop the inode lock while we're doing the I/O.
 		 * We'll still have the iolock to protect us.
 		 */
-		XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+		xfs_iunlock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
 
 		zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
 		zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
@@ -558,14 +550,13 @@
 		start_zero_fsb = imap.br_startoff + imap.br_blockcount;
 		ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
 
-		XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+		xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
 	}
 
 	return 0;
 
 out_lock:
-
-	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
 	ASSERT(error >= 0);
 	return error;
 }
@@ -587,7 +578,6 @@
 	xfs_mount_t		*mp;
 	ssize_t			ret = 0, error = 0;
 	xfs_fsize_t		isize, new_size;
-	xfs_iocore_t		*io;
 	int			iolock;
 	int			eventsent = 0;
 	bhv_vrwlock_t		locktype;
@@ -607,8 +597,7 @@
 	if (count == 0)
 		return 0;
 
-	io = &xip->i_iocore;
-	mp = io->io_mount;
+	mp = xip->i_mount;
 
 	xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
 
@@ -667,7 +656,7 @@
 
 	if (ioflags & IO_ISDIRECT) {
 		xfs_buftarg_t	*target =
-			(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
+			XFS_IS_REALTIME_INODE(xip) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
 
 		if ((pos & target->bt_smask) || (count & target->bt_smask)) {
@@ -688,7 +677,7 @@
 
 	new_size = pos + count;
 	if (new_size > xip->i_size)
-		io->io_new_size = new_size;
+		xip->i_new_size = new_size;
 
 	if (likely(!(ioflags & IO_INVIS))) {
 		file_update_time(file);
@@ -706,7 +695,7 @@
 	 */
 
 	if (pos > xip->i_size) {
-		error = xfs_zero_eof(vp, io, pos, xip->i_size);
+		error = xfs_zero_eof(xip, pos, xip->i_size);
 		if (error) {
 			xfs_iunlock(xip, XFS_ILOCK_EXCL);
 			goto out_unlock_internal;
@@ -740,10 +729,10 @@
 	if ((ioflags & IO_ISDIRECT)) {
 		if (VN_CACHED(vp)) {
 			WARN_ON(need_i_mutex == 0);
-			xfs_inval_cached_trace(io, pos, -1,
-					ctooff(offtoct(pos)), -1);
+			xfs_inval_cached_trace(xip, pos, -1,
+					(pos & PAGE_CACHE_MASK), -1);
 			error = xfs_flushinval_pages(xip,
-					ctooff(offtoct(pos)),
+					(pos & PAGE_CACHE_MASK),
 					-1, FI_REMAPF_LOCKED);
 			if (error)
 				goto out_unlock_internal;
@@ -751,7 +740,7 @@
 
 		if (need_i_mutex) {
 			/* demote the lock now the cached pages are gone */
-			XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
+			xfs_ilock_demote(xip, XFS_IOLOCK_EXCL);
 			mutex_unlock(&inode->i_mutex);
 
 			iolock = XFS_IOLOCK_SHARED;
@@ -759,7 +748,7 @@
 			need_i_mutex = 0;
 		}
 
- 		xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, (void *)iovp, segs,
+ 		xfs_rw_enter_trace(XFS_DIOWR_ENTER, xip, (void *)iovp, segs,
 				*offset, ioflags);
 		ret = generic_file_direct_write(iocb, iovp,
 				&segs, pos, offset, count, ocount);
@@ -779,7 +768,7 @@
 			goto relock;
 		}
 	} else {
-		xfs_rw_enter_trace(XFS_WRITE_ENTER, io, (void *)iovp, segs,
+		xfs_rw_enter_trace(XFS_WRITE_ENTER, xip, (void *)iovp, segs,
 				*offset, ioflags);
 		ret = generic_file_buffered_write(iocb, iovp, segs,
 				pos, offset, count, ret);
@@ -843,9 +832,9 @@
 	}
 
  out_unlock_internal:
-	if (io->io_new_size) {
+	if (xip->i_new_size) {
 		xfs_ilock(xip, XFS_ILOCK_EXCL);
-		io->io_new_size = 0;
+		xip->i_new_size = 0;
 		/*
 		 * If this was a direct or synchronous I/O that failed (such
 		 * as ENOSPC) then part of the I/O may have been written to
@@ -894,25 +883,6 @@
 	}
 }
 
-
-int
-xfs_bmap(
-	xfs_inode_t	*ip,
-	xfs_off_t	offset,
-	ssize_t		count,
-	int		flags,
-	xfs_iomap_t	*iomapp,
-	int		*niomaps)
-{
-	xfs_iocore_t	*io = &ip->i_iocore;
-
-	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
-	ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
-	       ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
-
-	return xfs_iomap(io, offset, count, flags, iomapp, niomaps);
-}
-
 /*
  * Wrapper around bdstrat so that we can stop data
  * from going to disk in case we are shutting down the filesystem.
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 4b7747a..e200253 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -19,7 +19,6 @@
 #define __XFS_LRW_H__
 
 struct xfs_mount;
-struct xfs_iocore;
 struct xfs_inode;
 struct xfs_bmbt_irec;
 struct xfs_buf;
@@ -60,20 +59,19 @@
 #define	XFS_IOMAP_UNWRITTEN	27
 #define XFS_SPLICE_READ_ENTER	28
 #define XFS_SPLICE_WRITE_ENTER	29
-extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
-				void *, size_t, loff_t, int);
-extern void xfs_inval_cached_trace(struct xfs_iocore *,
-				xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
+extern void xfs_rw_enter_trace(int, struct xfs_inode *,
+		void *, size_t, loff_t, int);
+extern void xfs_inval_cached_trace(struct xfs_inode *,
+		xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
 #else
-#define xfs_rw_enter_trace(tag, io, data, size, offset, ioflags)
-#define xfs_inval_cached_trace(io, offset, len, first, last)
+#define xfs_rw_enter_trace(tag, ip, data, size, offset, ioflags)
+#define xfs_inval_cached_trace(ip, offset, len, first, last)
 #endif
 
 extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
 extern int xfs_bdstrat_cb(struct xfs_buf *);
 extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
 
-extern int xfs_zero_eof(struct inode *, struct xfs_iocore *, xfs_off_t,
-				xfs_fsize_t);
+extern int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
 
 #endif	/* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 8cb63c6..21dfc9d 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -41,6 +41,7 @@
 #include "xfs_rtalloc.h"
 #include "xfs_error.h"
 #include "xfs_itable.h"
+#include "xfs_fsops.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
 #include "xfs_attr.h"
@@ -49,6 +50,8 @@
 #include "xfs_vnodeops.h"
 #include "xfs_vfsops.h"
 #include "xfs_version.h"
+#include "xfs_log_priv.h"
+#include "xfs_trans_priv.h"
 
 #include <linux/namei.h>
 #include <linux/init.h>
@@ -87,6 +90,435 @@
 	return args;
 }
 
+#define MNTOPT_LOGBUFS	"logbufs"	/* number of XFS log buffers */
+#define MNTOPT_LOGBSIZE	"logbsize"	/* size of XFS log buffers */
+#define MNTOPT_LOGDEV	"logdev"	/* log device */
+#define MNTOPT_RTDEV	"rtdev"		/* realtime I/O device */
+#define MNTOPT_BIOSIZE	"biosize"	/* log2 of preferred buffered io size */
+#define MNTOPT_WSYNC	"wsync"		/* safe-mode nfs compatible mount */
+#define MNTOPT_INO64	"ino64"		/* force inodes into 64-bit range */
+#define MNTOPT_NOALIGN	"noalign"	/* turn off stripe alignment */
+#define MNTOPT_SWALLOC	"swalloc"	/* turn on stripe width allocation */
+#define MNTOPT_SUNIT	"sunit"		/* data volume stripe unit */
+#define MNTOPT_SWIDTH	"swidth"	/* data volume stripe width */
+#define MNTOPT_NOUUID	"nouuid"	/* ignore filesystem UUID */
+#define MNTOPT_MTPT	"mtpt"		/* filesystem mount point */
+#define MNTOPT_GRPID	"grpid"		/* group-ID from parent directory */
+#define MNTOPT_NOGRPID	"nogrpid"	/* group-ID from current process */
+#define MNTOPT_BSDGROUPS    "bsdgroups"    /* group-ID from parent directory */
+#define MNTOPT_SYSVGROUPS   "sysvgroups"   /* group-ID from current process */
+#define MNTOPT_ALLOCSIZE    "allocsize"    /* preferred allocation size */
+#define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */
+#define MNTOPT_BARRIER	"barrier"	/* use writer barriers for log write and
+					 * unwritten extent conversion */
+#define MNTOPT_NOBARRIER "nobarrier"	/* .. disable */
+#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
+#define MNTOPT_64BITINODE   "inode64"	/* inodes can be allocated anywhere */
+#define MNTOPT_IKEEP	"ikeep"		/* do not free empty inode clusters */
+#define MNTOPT_NOIKEEP	"noikeep"	/* free empty inode clusters */
+#define MNTOPT_LARGEIO	   "largeio"	/* report large I/O sizes in stat() */
+#define MNTOPT_NOLARGEIO   "nolargeio"	/* do not report large I/O sizes
+					 * in stat(). */
+#define MNTOPT_ATTR2	"attr2"		/* do use attr2 attribute format */
+#define MNTOPT_NOATTR2	"noattr2"	/* do not use attr2 attribute format */
+#define MNTOPT_FILESTREAM  "filestreams" /* use filestreams allocator */
+#define MNTOPT_QUOTA	"quota"		/* disk quotas (user) */
+#define MNTOPT_NOQUOTA	"noquota"	/* no quotas */
+#define MNTOPT_USRQUOTA	"usrquota"	/* user quota enabled */
+#define MNTOPT_GRPQUOTA	"grpquota"	/* group quota enabled */
+#define MNTOPT_PRJQUOTA	"prjquota"	/* project quota enabled */
+#define MNTOPT_UQUOTA	"uquota"	/* user quota (IRIX variant) */
+#define MNTOPT_GQUOTA	"gquota"	/* group quota (IRIX variant) */
+#define MNTOPT_PQUOTA	"pquota"	/* project quota (IRIX variant) */
+#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
+#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
+#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
+#define MNTOPT_QUOTANOENF  "qnoenforce"	/* same as uqnoenforce */
+#define MNTOPT_DMAPI	"dmapi"		/* DMI enabled (DMAPI / XDSM) */
+#define MNTOPT_XDSM	"xdsm"		/* DMI enabled (DMAPI / XDSM) */
+#define MNTOPT_DMI	"dmi"		/* DMI enabled (DMAPI / XDSM) */
+
+STATIC unsigned long
+suffix_strtoul(char *s, char **endp, unsigned int base)
+{
+	int	last, shift_left_factor = 0;
+	char	*value = s;
+
+	last = strlen(value) - 1;
+	if (value[last] == 'K' || value[last] == 'k') {
+		shift_left_factor = 10;
+		value[last] = '\0';
+	}
+	if (value[last] == 'M' || value[last] == 'm') {
+		shift_left_factor = 20;
+		value[last] = '\0';
+	}
+	if (value[last] == 'G' || value[last] == 'g') {
+		shift_left_factor = 30;
+		value[last] = '\0';
+	}
+
+	return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
+}
+
+STATIC int
+xfs_parseargs(
+	struct xfs_mount	*mp,
+	char			*options,
+	struct xfs_mount_args	*args,
+	int			update)
+{
+	char			*this_char, *value, *eov;
+	int			dsunit, dswidth, vol_dsunit, vol_dswidth;
+	int			iosize;
+	int			ikeep = 0;
+
+	args->flags |= XFSMNT_BARRIER;
+	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
+
+	if (!options)
+		goto done;
+
+	iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
+
+	while ((this_char = strsep(&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
+		if ((value = strchr(this_char, '=')) != NULL)
+			*value++ = 0;
+
+		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			args->logbufs = simple_strtoul(value, &eov, 10);
+		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			args->logbufsize = suffix_strtoul(value, &eov, 10);
+		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			strncpy(args->logname, value, MAXNAMELEN);
+		} else if (!strcmp(this_char, MNTOPT_MTPT)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			strncpy(args->mtpt, value, MAXNAMELEN);
+		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			strncpy(args->rtname, value, MAXNAMELEN);
+		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			iosize = simple_strtoul(value, &eov, 10);
+			args->flags |= XFSMNT_IOSIZE;
+			args->iosizelog = (uint8_t) iosize;
+		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			iosize = suffix_strtoul(value, &eov, 10);
+			args->flags |= XFSMNT_IOSIZE;
+			args->iosizelog = ffs(iosize) - 1;
+		} else if (!strcmp(this_char, MNTOPT_GRPID) ||
+			   !strcmp(this_char, MNTOPT_BSDGROUPS)) {
+			mp->m_flags |= XFS_MOUNT_GRPID;
+		} else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
+			   !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
+			mp->m_flags &= ~XFS_MOUNT_GRPID;
+		} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
+			args->flags |= XFSMNT_WSYNC;
+		} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
+			args->flags |= XFSMNT_OSYNCISOSYNC;
+		} else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
+			args->flags |= XFSMNT_NORECOVERY;
+		} else if (!strcmp(this_char, MNTOPT_INO64)) {
+			args->flags |= XFSMNT_INO64;
+#if !XFS_BIG_INUMS
+			cmn_err(CE_WARN,
+				"XFS: %s option not allowed on this system",
+				this_char);
+			return EINVAL;
+#endif
+		} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
+			args->flags |= XFSMNT_NOALIGN;
+		} else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
+			args->flags |= XFSMNT_SWALLOC;
+		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			dsunit = simple_strtoul(value, &eov, 10);
+		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
+			if (!value || !*value) {
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			dswidth = simple_strtoul(value, &eov, 10);
+		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
+			args->flags &= ~XFSMNT_32BITINODES;
+#if !XFS_BIG_INUMS
+			cmn_err(CE_WARN,
+				"XFS: %s option not allowed on this system",
+				this_char);
+			return EINVAL;
+#endif
+		} else if (!strcmp(this_char, MNTOPT_NOUUID)) {
+			args->flags |= XFSMNT_NOUUID;
+		} else if (!strcmp(this_char, MNTOPT_BARRIER)) {
+			args->flags |= XFSMNT_BARRIER;
+		} else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
+			args->flags &= ~XFSMNT_BARRIER;
+		} else if (!strcmp(this_char, MNTOPT_IKEEP)) {
+			ikeep = 1;
+			args->flags &= ~XFSMNT_IDELETE;
+		} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
+			args->flags |= XFSMNT_IDELETE;
+		} else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
+			args->flags2 &= ~XFSMNT2_COMPAT_IOSIZE;
+		} else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
+			args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
+		} else if (!strcmp(this_char, MNTOPT_ATTR2)) {
+			args->flags |= XFSMNT_ATTR2;
+		} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
+			args->flags &= ~XFSMNT_ATTR2;
+		} else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
+			args->flags2 |= XFSMNT2_FILESTREAMS;
+		} else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
+			args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
+			args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
+		} else if (!strcmp(this_char, MNTOPT_QUOTA) ||
+			   !strcmp(this_char, MNTOPT_UQUOTA) ||
+			   !strcmp(this_char, MNTOPT_USRQUOTA)) {
+			args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
+		} else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
+			   !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
+			args->flags |= XFSMNT_UQUOTA;
+			args->flags &= ~XFSMNT_UQUOTAENF;
+		} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
+			   !strcmp(this_char, MNTOPT_PRJQUOTA)) {
+			args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
+		} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
+			args->flags |= XFSMNT_PQUOTA;
+			args->flags &= ~XFSMNT_PQUOTAENF;
+		} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
+			   !strcmp(this_char, MNTOPT_GRPQUOTA)) {
+			args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
+		} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
+			args->flags |= XFSMNT_GQUOTA;
+			args->flags &= ~XFSMNT_GQUOTAENF;
+		} else if (!strcmp(this_char, MNTOPT_DMAPI)) {
+			args->flags |= XFSMNT_DMAPI;
+		} else if (!strcmp(this_char, MNTOPT_XDSM)) {
+			args->flags |= XFSMNT_DMAPI;
+		} else if (!strcmp(this_char, MNTOPT_DMI)) {
+			args->flags |= XFSMNT_DMAPI;
+		} else if (!strcmp(this_char, "ihashsize")) {
+			cmn_err(CE_WARN,
+	"XFS: ihashsize no longer used, option is deprecated.");
+		} else if (!strcmp(this_char, "osyncisdsync")) {
+			/* no-op, this is now the default */
+			cmn_err(CE_WARN,
+	"XFS: osyncisdsync is now the default, option is deprecated.");
+		} else if (!strcmp(this_char, "irixsgid")) {
+			cmn_err(CE_WARN,
+	"XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
+		} else {
+			cmn_err(CE_WARN,
+				"XFS: unknown mount option [%s].", this_char);
+			return EINVAL;
+		}
+	}
+
+	if (args->flags & XFSMNT_NORECOVERY) {
+		if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) {
+			cmn_err(CE_WARN,
+				"XFS: no-recovery mounts must be read-only.");
+			return EINVAL;
+		}
+	}
+
+	if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
+		cmn_err(CE_WARN,
+	"XFS: sunit and swidth options incompatible with the noalign option");
+		return EINVAL;
+	}
+
+	if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
+		cmn_err(CE_WARN,
+			"XFS: cannot mount with both project and group quota");
+		return EINVAL;
+	}
+
+	if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
+		printk("XFS: %s option needs the mount point option as well\n",
+			MNTOPT_DMAPI);
+		return EINVAL;
+	}
+
+	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
+		cmn_err(CE_WARN,
+			"XFS: sunit and swidth must be specified together");
+		return EINVAL;
+	}
+
+	if (dsunit && (dswidth % dsunit != 0)) {
+		cmn_err(CE_WARN,
+	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
+			dswidth, dsunit);
+		return EINVAL;
+	}
+
+	/*
+	 * Applications using DMI filesystems often expect the
+	 * inode generation number to be monotonically increasing.
+	 * If we delete inode chunks we break this assumption, so
+	 * keep unused inode chunks on disk for DMI filesystems
+	 * until we come up with a better solution.
+	 * Note that if "ikeep" or "noikeep" mount options are
+	 * supplied, then they are honored.
+	 */
+	if (!(args->flags & XFSMNT_DMAPI) && !ikeep)
+		args->flags |= XFSMNT_IDELETE;
+
+	if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
+		if (dsunit) {
+			args->sunit = dsunit;
+			args->flags |= XFSMNT_RETERR;
+		} else {
+			args->sunit = vol_dsunit;
+		}
+		dswidth ? (args->swidth = dswidth) :
+			  (args->swidth = vol_dswidth);
+	} else {
+		args->sunit = args->swidth = 0;
+	}
+
+done:
+	if (args->flags & XFSMNT_32BITINODES)
+		mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
+	if (args->flags2)
+		args->flags |= XFSMNT_FLAGS2;
+	return 0;
+}
+
+struct proc_xfs_info {
+	int	flag;
+	char	*str;
+};
+
+STATIC int
+xfs_showargs(
+	struct xfs_mount	*mp,
+	struct seq_file		*m)
+{
+	static struct proc_xfs_info xfs_info_set[] = {
+		/* the few simple ones we can get from the mount struct */
+		{ XFS_MOUNT_WSYNC,		"," MNTOPT_WSYNC },
+		{ XFS_MOUNT_INO64,		"," MNTOPT_INO64 },
+		{ XFS_MOUNT_NOALIGN,		"," MNTOPT_NOALIGN },
+		{ XFS_MOUNT_SWALLOC,		"," MNTOPT_SWALLOC },
+		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID },
+		{ XFS_MOUNT_NORECOVERY,		"," MNTOPT_NORECOVERY },
+		{ XFS_MOUNT_OSYNCISOSYNC,	"," MNTOPT_OSYNCISOSYNC },
+		{ XFS_MOUNT_ATTR2,		"," MNTOPT_ATTR2 },
+		{ XFS_MOUNT_FILESTREAMS,	"," MNTOPT_FILESTREAM },
+		{ XFS_MOUNT_DMAPI,		"," MNTOPT_DMAPI },
+		{ XFS_MOUNT_GRPID,		"," MNTOPT_GRPID },
+		{ 0, NULL }
+	};
+	static struct proc_xfs_info xfs_info_unset[] = {
+		/* the few simple ones we can get from the mount struct */
+		{ XFS_MOUNT_IDELETE,		"," MNTOPT_IKEEP },
+		{ XFS_MOUNT_COMPAT_IOSIZE,	"," MNTOPT_LARGEIO },
+		{ XFS_MOUNT_BARRIER,		"," MNTOPT_NOBARRIER },
+		{ XFS_MOUNT_SMALL_INUMS,	"," MNTOPT_64BITINODE },
+		{ 0, NULL }
+	};
+	struct proc_xfs_info	*xfs_infop;
+
+	for (xfs_infop = xfs_info_set; xfs_infop->flag; xfs_infop++) {
+		if (mp->m_flags & xfs_infop->flag)
+			seq_puts(m, xfs_infop->str);
+	}
+	for (xfs_infop = xfs_info_unset; xfs_infop->flag; xfs_infop++) {
+		if (!(mp->m_flags & xfs_infop->flag))
+			seq_puts(m, xfs_infop->str);
+	}
+
+	if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
+		seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
+				(int)(1 << mp->m_writeio_log) >> 10);
+
+	if (mp->m_logbufs > 0)
+		seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
+	if (mp->m_logbsize > 0)
+		seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
+
+	if (mp->m_logname)
+		seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
+	if (mp->m_rtname)
+		seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
+
+	if (mp->m_dalign > 0)
+		seq_printf(m, "," MNTOPT_SUNIT "=%d",
+				(int)XFS_FSB_TO_BB(mp, mp->m_dalign));
+	if (mp->m_swidth > 0)
+		seq_printf(m, "," MNTOPT_SWIDTH "=%d",
+				(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
+
+	if (mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD))
+		seq_puts(m, "," MNTOPT_USRQUOTA);
+	else if (mp->m_qflags & XFS_UQUOTA_ACCT)
+		seq_puts(m, "," MNTOPT_UQUOTANOENF);
+
+	if (mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
+		seq_puts(m, "," MNTOPT_PRJQUOTA);
+	else if (mp->m_qflags & XFS_PQUOTA_ACCT)
+		seq_puts(m, "," MNTOPT_PQUOTANOENF);
+
+	if (mp->m_qflags & (XFS_GQUOTA_ACCT|XFS_OQUOTA_ENFD))
+		seq_puts(m, "," MNTOPT_GRPQUOTA);
+	else if (mp->m_qflags & XFS_GQUOTA_ACCT)
+		seq_puts(m, "," MNTOPT_GQUOTANOENF);
+
+	if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
+		seq_puts(m, "," MNTOPT_NOQUOTA);
+
+	return 0;
+}
 __uint64_t
 xfs_max_file_offset(
 	unsigned int		blockshift)
@@ -137,7 +569,7 @@
 		break;
 	case S_IFLNK:
 		inode->i_op = &xfs_symlink_inode_operations;
-		if (inode->i_blocks)
+		if (!(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE))
 			inode->i_mapping->a_ops = &xfs_address_space_operations;
 		break;
 	default:
@@ -174,8 +606,6 @@
 
 	inode->i_generation = ip->i_d.di_gen;
 	i_size_write(inode, ip->i_d.di_size);
-	inode->i_blocks =
-		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
 	inode->i_atime.tv_sec	= ip->i_d.di_atime.t_sec;
 	inode->i_atime.tv_nsec	= ip->i_d.di_atime.t_nsec;
 	inode->i_mtime.tv_sec	= ip->i_d.di_mtime.t_sec;
@@ -334,6 +764,64 @@
 	blkdev_issue_flush(buftarg->bt_bdev, NULL);
 }
 
+/*
+ * XFS AIL push thread support
+ */
+void
+xfsaild_wakeup(
+	xfs_mount_t		*mp,
+	xfs_lsn_t		threshold_lsn)
+{
+	mp->m_ail.xa_target = threshold_lsn;
+	wake_up_process(mp->m_ail.xa_task);
+}
+
+int
+xfsaild(
+	void	*data)
+{
+	xfs_mount_t	*mp = (xfs_mount_t *)data;
+	xfs_lsn_t	last_pushed_lsn = 0;
+	long		tout = 0;
+
+	while (!kthread_should_stop()) {
+		if (tout)
+			schedule_timeout_interruptible(msecs_to_jiffies(tout));
+		tout = 1000;
+
+		/* swsusp */
+		try_to_freeze();
+
+		ASSERT(mp->m_log);
+		if (XFS_FORCED_SHUTDOWN(mp))
+			continue;
+
+		tout = xfsaild_push(mp, &last_pushed_lsn);
+	}
+
+	return 0;
+}	/* xfsaild */
+
+int
+xfsaild_start(
+	xfs_mount_t	*mp)
+{
+	mp->m_ail.xa_target = 0;
+	mp->m_ail.xa_task = kthread_run(xfsaild, mp, "xfsaild");
+	if (IS_ERR(mp->m_ail.xa_task))
+		return -PTR_ERR(mp->m_ail.xa_task);
+	return 0;
+}
+
+void
+xfsaild_stop(
+	xfs_mount_t	*mp)
+{
+	kthread_stop(mp->m_ail.xa_task);
+}
+
+
+
 STATIC struct inode *
 xfs_fs_alloc_inode(
 	struct super_block	*sb)
@@ -361,7 +849,7 @@
 	inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
 }
 
-STATIC int
+STATIC int __init
 xfs_init_zones(void)
 {
 	xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode",
@@ -410,8 +898,7 @@
 {
 	int			error = 0, flags = FLUSH_INODE;
 
-	vn_trace_entry(XFS_I(inode), __FUNCTION__,
-			(inst_t *)__return_address);
+	xfs_itrace_entry(XFS_I(inode));
 	if (sync) {
 		filemap_fdatawait(inode->i_mapping);
 		flags |= FLUSH_SYNC;
@@ -438,8 +925,7 @@
 	 * find an inode with di_mode == 0 but without IGET_CREATE set.
 	 */
 	if (ip) {
-		vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
-
+		xfs_itrace_entry(ip);
 		XFS_STATS_INC(vn_rele);
 		XFS_STATS_INC(vn_remove);
 		XFS_STATS_INC(vn_reclaim);
@@ -683,8 +1169,44 @@
 	struct dentry		*dentry,
 	struct kstatfs		*statp)
 {
-	return -xfs_statvfs(XFS_M(dentry->d_sb), statp,
-				vn_from_inode(dentry->d_inode));
+	struct xfs_mount	*mp = XFS_M(dentry->d_sb);
+	xfs_sb_t		*sbp = &mp->m_sb;
+	__uint64_t		fakeinos, id;
+	xfs_extlen_t		lsize;
+
+	statp->f_type = XFS_SB_MAGIC;
+	statp->f_namelen = MAXNAMELEN - 1;
+
+	id = huge_encode_dev(mp->m_ddev_targp->bt_dev);
+	statp->f_fsid.val[0] = (u32)id;
+	statp->f_fsid.val[1] = (u32)(id >> 32);
+
+	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
+
+	spin_lock(&mp->m_sb_lock);
+	statp->f_bsize = sbp->sb_blocksize;
+	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
+	statp->f_blocks = sbp->sb_dblocks - lsize;
+	statp->f_bfree = statp->f_bavail =
+				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+	fakeinos = statp->f_bfree << sbp->sb_inopblog;
+#if XFS_BIG_INUMS
+	fakeinos += mp->m_inoadd;
+#endif
+	statp->f_files =
+	    MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
+	if (mp->m_maxicount)
+#if XFS_BIG_INUMS
+		if (!mp->m_inoadd)
+#endif
+			statp->f_files = min_t(typeof(statp->f_files),
+						statp->f_files,
+						mp->m_maxicount);
+	statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
+	spin_unlock(&mp->m_sb_lock);
+
+	XFS_QM_DQSTATVFS(XFS_I(dentry->d_inode), statp);
+	return 0;
 }
 
 STATIC int
@@ -704,11 +1226,19 @@
 	return -error;
 }
 
+/*
+ * Second stage of a freeze. The data is already frozen so we only
+ * need to take care of themetadata. Once that's done write a dummy
+ * record to dirty the log in case of a crash while frozen.
+ */
 STATIC void
 xfs_fs_lockfs(
 	struct super_block	*sb)
 {
-	xfs_freeze(XFS_M(sb));
+	struct xfs_mount	*mp = XFS_M(sb);
+
+	xfs_attr_quiesce(mp);
+	xfs_fs_log_dummy(mp);
 }
 
 STATIC int
@@ -779,7 +1309,6 @@
 	struct inode		*rootvp;
 	struct xfs_mount	*mp = NULL;
 	struct xfs_mount_args	*args = xfs_args_allocate(sb, silent);
-	struct kstatfs		statvfs;
 	int			error;
 
 	mp = xfs_mount_init();
@@ -807,21 +1336,19 @@
 	if (error)
 		goto fail_vfsop;
 
-	error = xfs_statvfs(mp, &statvfs, NULL);
-	if (error)
-		goto fail_unmount;
-
 	sb->s_dirt = 1;
-	sb->s_magic = statvfs.f_type;
-	sb->s_blocksize = statvfs.f_bsize;
-	sb->s_blocksize_bits = ffs(statvfs.f_bsize) - 1;
+	sb->s_magic = XFS_SB_MAGIC;
+	sb->s_blocksize = mp->m_sb.sb_blocksize;
+	sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
 	sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits);
 	sb->s_time_gran = 1;
 	set_posix_acl_flag(sb);
 
-	error = xfs_root(mp, &rootvp);
-	if (error)
+	rootvp = igrab(mp->m_rootip->i_vnode);
+	if (!rootvp) {
+		error = ENOENT;
 		goto fail_unmount;
+	}
 
 	sb->s_root = d_alloc_root(vn_to_inode(rootvp));
 	if (!sb->s_root) {
@@ -841,8 +1368,7 @@
 		goto fail_vnrele;
 	}
 
-	vn_trace_exit(XFS_I(sb->s_root->d_inode), __FUNCTION__,
-			(inst_t *)__return_address);
+	xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
 
 	kmem_free(args, sizeof(*args));
 	return 0;
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 814169f..bc7afe0 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -40,7 +40,7 @@
 #define vptosync(v)             (&vsync[((unsigned long)v) % NVSYNC])
 static wait_queue_head_t vsync[NVSYNC];
 
-void
+void __init
 vn_init(void)
 {
 	int i;
@@ -82,84 +82,55 @@
 		xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l);
 }
 
-bhv_vnode_t *
-vn_initialize(
-	struct inode	*inode)
-{
-	bhv_vnode_t	*vp = vn_from_inode(inode);
-
-	XFS_STATS_INC(vn_active);
-	XFS_STATS_INC(vn_alloc);
-
-	ASSERT(VN_CACHED(vp) == 0);
-
-	return vp;
-}
-
 /*
- * Revalidate the Linux inode from the vattr.
+ * Revalidate the Linux inode from the XFS inode.
  * Note: i_size _not_ updated; we must hold the inode
  * semaphore when doing that - callers responsibility.
  */
-void
-vn_revalidate_core(
-	bhv_vnode_t	*vp,
-	bhv_vattr_t	*vap)
+int
+vn_revalidate(
+	bhv_vnode_t		*vp)
 {
-	struct inode	*inode = vn_to_inode(vp);
+	struct inode		*inode = vn_to_inode(vp);
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	unsigned long		xflags;
 
-	inode->i_mode	    = vap->va_mode;
-	inode->i_nlink	    = vap->va_nlink;
-	inode->i_uid	    = vap->va_uid;
-	inode->i_gid	    = vap->va_gid;
-	inode->i_blocks	    = vap->va_nblocks;
-	inode->i_mtime	    = vap->va_mtime;
-	inode->i_ctime	    = vap->va_ctime;
-	if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
+	xfs_itrace_entry(ip);
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_ILOCK_SHARED);
+	inode->i_mode	    = ip->i_d.di_mode;
+	inode->i_uid	    = ip->i_d.di_uid;
+	inode->i_gid	    = ip->i_d.di_gid;
+	inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
+	inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
+	inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
+	inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
+
+	xflags = xfs_ip2xflags(ip);
+	if (xflags & XFS_XFLAG_IMMUTABLE)
 		inode->i_flags |= S_IMMUTABLE;
 	else
 		inode->i_flags &= ~S_IMMUTABLE;
-	if (vap->va_xflags & XFS_XFLAG_APPEND)
+	if (xflags & XFS_XFLAG_APPEND)
 		inode->i_flags |= S_APPEND;
 	else
 		inode->i_flags &= ~S_APPEND;
-	if (vap->va_xflags & XFS_XFLAG_SYNC)
+	if (xflags & XFS_XFLAG_SYNC)
 		inode->i_flags |= S_SYNC;
 	else
 		inode->i_flags &= ~S_SYNC;
-	if (vap->va_xflags & XFS_XFLAG_NOATIME)
+	if (xflags & XFS_XFLAG_NOATIME)
 		inode->i_flags |= S_NOATIME;
 	else
 		inode->i_flags &= ~S_NOATIME;
-}
+	xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
-/*
- * Revalidate the Linux inode from the vnode.
- */
-int
-__vn_revalidate(
-	bhv_vnode_t	*vp,
-	bhv_vattr_t	*vattr)
-{
-	int		error;
-
-	vn_trace_entry(xfs_vtoi(vp), __FUNCTION__, (inst_t *)__return_address);
-	vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
-	error = xfs_getattr(xfs_vtoi(vp), vattr, 0);
-	if (likely(!error)) {
-		vn_revalidate_core(vp, vattr);
-		xfs_iflags_clear(xfs_vtoi(vp), XFS_IMODIFIED);
-	}
-	return -error;
-}
-
-int
-vn_revalidate(
-	bhv_vnode_t	*vp)
-{
-	bhv_vattr_t	vattr;
-
-	return __vn_revalidate(vp, &vattr);
+	xfs_iflags_clear(ip, XFS_IMODIFIED);
+	return 0;
 }
 
 /*
@@ -179,7 +150,7 @@
 	return vp;
 }
 
-#ifdef	XFS_VNODE_TRACE
+#ifdef	XFS_INODE_TRACE
 
 /*
  * Reference count of Linux inode if present, -1 if the xfs_inode
@@ -211,32 +182,32 @@
  * Vnode tracing code.
  */
 void
-vn_trace_entry(xfs_inode_t *ip, const char *func, inst_t *ra)
+_xfs_itrace_entry(xfs_inode_t *ip, const char *func, inst_t *ra)
 {
-	KTRACE_ENTER(ip, VNODE_KTRACE_ENTRY, func, 0, ra);
+	KTRACE_ENTER(ip, INODE_KTRACE_ENTRY, func, 0, ra);
 }
 
 void
-vn_trace_exit(xfs_inode_t *ip, const char *func, inst_t *ra)
+_xfs_itrace_exit(xfs_inode_t *ip, const char *func, inst_t *ra)
 {
-	KTRACE_ENTER(ip, VNODE_KTRACE_EXIT, func, 0, ra);
+	KTRACE_ENTER(ip, INODE_KTRACE_EXIT, func, 0, ra);
 }
 
 void
-vn_trace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra)
+xfs_itrace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra)
 {
-	KTRACE_ENTER(ip, VNODE_KTRACE_HOLD, file, line, ra);
+	KTRACE_ENTER(ip, INODE_KTRACE_HOLD, file, line, ra);
 }
 
 void
-vn_trace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra)
+_xfs_itrace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra)
 {
-	KTRACE_ENTER(ip, VNODE_KTRACE_REF, file, line, ra);
+	KTRACE_ENTER(ip, INODE_KTRACE_REF, file, line, ra);
 }
 
 void
-vn_trace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra)
+xfs_itrace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra)
 {
-	KTRACE_ENTER(ip, VNODE_KTRACE_RELE, file, line, ra);
+	KTRACE_ENTER(ip, INODE_KTRACE_RELE, file, line, ra);
 }
-#endif	/* XFS_VNODE_TRACE */
+#endif	/* XFS_INODE_TRACE */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 55fb469..b5ea418 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -187,10 +187,7 @@
 	(VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
 
 extern void	vn_init(void);
-extern bhv_vnode_t	*vn_initialize(struct inode *);
 extern int	vn_revalidate(bhv_vnode_t *);
-extern int	__vn_revalidate(bhv_vnode_t *, bhv_vattr_t *);
-extern void	vn_revalidate_core(bhv_vnode_t *, bhv_vattr_t *);
 
 /*
  * Yeah, these don't take vnode anymore at all, all this should be
@@ -210,12 +207,12 @@
  */
 extern bhv_vnode_t	*vn_hold(bhv_vnode_t *);
 
-#if defined(XFS_VNODE_TRACE)
+#if defined(XFS_INODE_TRACE)
 #define VN_HOLD(vp)		\
 	((void)vn_hold(vp),	\
-	  vn_trace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address))
+	  xfs_itrace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address))
 #define VN_RELE(vp)		\
-	  (vn_trace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \
+	  (xfs_itrace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \
 	   iput(vn_to_inode(vp)))
 #else
 #define VN_HOLD(vp)		((void)vn_hold(vp))
@@ -238,11 +235,6 @@
 /*
  * Dealing with bad inodes
  */
-static inline void vn_mark_bad(bhv_vnode_t *vp)
-{
-	make_bad_inode(vn_to_inode(vp));
-}
-
 static inline int VN_BAD(bhv_vnode_t *vp)
 {
 	return is_bad_inode(vn_to_inode(vp));
@@ -296,26 +288,36 @@
 /*
  * Tracking vnode activity.
  */
-#if defined(XFS_VNODE_TRACE)
+#if defined(XFS_INODE_TRACE)
 
-#define	VNODE_TRACE_SIZE	16		/* number of trace entries */
-#define	VNODE_KTRACE_ENTRY	1
-#define	VNODE_KTRACE_EXIT	2
-#define	VNODE_KTRACE_HOLD	3
-#define	VNODE_KTRACE_REF	4
-#define	VNODE_KTRACE_RELE	5
+#define	INODE_TRACE_SIZE	16		/* number of trace entries */
+#define	INODE_KTRACE_ENTRY	1
+#define	INODE_KTRACE_EXIT	2
+#define	INODE_KTRACE_HOLD	3
+#define	INODE_KTRACE_REF	4
+#define	INODE_KTRACE_RELE	5
 
-extern void vn_trace_entry(struct xfs_inode *, const char *, inst_t *);
-extern void vn_trace_exit(struct xfs_inode *, const char *, inst_t *);
-extern void vn_trace_hold(struct xfs_inode *, char *, int, inst_t *);
-extern void vn_trace_ref(struct xfs_inode *, char *, int, inst_t *);
-extern void vn_trace_rele(struct xfs_inode *, char *, int, inst_t *);
+extern void _xfs_itrace_entry(struct xfs_inode *, const char *, inst_t *);
+extern void _xfs_itrace_exit(struct xfs_inode *, const char *, inst_t *);
+extern void xfs_itrace_hold(struct xfs_inode *, char *, int, inst_t *);
+extern void _xfs_itrace_ref(struct xfs_inode *, char *, int, inst_t *);
+extern void xfs_itrace_rele(struct xfs_inode *, char *, int, inst_t *);
+#define xfs_itrace_entry(ip)	\
+	_xfs_itrace_entry(ip, __FUNCTION__, (inst_t *)__return_address)
+#define xfs_itrace_exit(ip)	\
+	_xfs_itrace_exit(ip, __FUNCTION__, (inst_t *)__return_address)
+#define xfs_itrace_exit_tag(ip, tag)	\
+	_xfs_itrace_exit(ip, tag, (inst_t *)__return_address)
+#define xfs_itrace_ref(ip)	\
+	_xfs_itrace_ref(ip, __FILE__, __LINE__, (inst_t *)__return_address)
+
 #else
-#define	vn_trace_entry(a,b,c)
-#define	vn_trace_exit(a,b,c)
-#define	vn_trace_hold(a,b,c,d)
-#define	vn_trace_ref(a,b,c,d)
-#define	vn_trace_rele(a,b,c,d)
+#define	xfs_itrace_entry(a)
+#define	xfs_itrace_exit(a)
+#define	xfs_itrace_exit_tag(a, b)
+#define	xfs_itrace_hold(a, b, c, d)
+#define	xfs_itrace_ref(a)
+#define	xfs_itrace_rele(a, b, c, d)
 #endif
 
 #endif	/* __XFS_VNODE_H__ */
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index cfdd35e..665babc 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -1209,7 +1209,6 @@
 	xfs_buf_t		*bp;
 	xfs_disk_dquot_t	*ddqp;
 	int			error;
-	SPLDECL(s);
 
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));
@@ -1270,9 +1269,9 @@
 	mp = dqp->q_mount;
 
 	/* lsn is 64 bits */
-	AIL_LOCK(mp, s);
+	spin_lock(&mp->m_ail_lock);
 	dqp->q_logitem.qli_flush_lsn = dqp->q_logitem.qli_item.li_lsn;
-	AIL_UNLOCK(mp, s);
+	spin_unlock(&mp->m_ail_lock);
 
 	/*
 	 * Attach an iodone routine so that we can remove this dquot from the
@@ -1318,7 +1317,6 @@
 	xfs_dq_logitem_t	*qip)
 {
 	xfs_dquot_t		*dqp;
-	SPLDECL(s);
 
 	dqp = qip->qli_dquot;
 
@@ -1333,15 +1331,15 @@
 	if ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
 	    qip->qli_item.li_lsn == qip->qli_flush_lsn) {
 
-		AIL_LOCK(dqp->q_mount, s);
+		spin_lock(&dqp->q_mount->m_ail_lock);
 		/*
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
 		if (qip->qli_item.li_lsn == qip->qli_flush_lsn)
 			xfs_trans_delete_ail(dqp->q_mount,
-					     (xfs_log_item_t*)qip, s);
+					     (xfs_log_item_t*)qip);
 		else
-			AIL_UNLOCK(dqp->q_mount, s);
+			spin_unlock(&dqp->q_mount->m_ail_lock);
 	}
 
 	/*
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 78d3ab9..5c371a9 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -123,11 +123,6 @@
 				   vsema(&((dqp)->q_flock)); \
 				   (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); }
 
-#define XFS_DQ_PINLOCK(dqp)	   mutex_spinlock( \
-				     &(XFS_DQ_TO_QINF(dqp)->qi_pinlock))
-#define XFS_DQ_PINUNLOCK(dqp, s)   mutex_spinunlock( \
-				     &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s)
-
 #define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock)))
 #define XFS_DQ_IS_ON_FREELIST(dqp)  ((dqp)->dq_flnext != (dqp))
 #define XFS_DQ_IS_DIRTY(dqp)	((dqp)->dq_flags & XFS_DQ_DIRTY)
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index ddb61fe..1800e8d 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -94,14 +94,13 @@
 xfs_qm_dquot_logitem_pin(
 	xfs_dq_logitem_t *logitem)
 {
-	unsigned long	s;
 	xfs_dquot_t *dqp;
 
 	dqp = logitem->qli_dquot;
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
-	s = XFS_DQ_PINLOCK(dqp);
+	spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
 	dqp->q_pincount++;
-	XFS_DQ_PINUNLOCK(dqp, s);
+	spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
 }
 
 /*
@@ -115,17 +114,16 @@
 	xfs_dq_logitem_t *logitem,
 	int		  stale)
 {
-	unsigned long	s;
 	xfs_dquot_t *dqp;
 
 	dqp = logitem->qli_dquot;
 	ASSERT(dqp->q_pincount > 0);
-	s = XFS_DQ_PINLOCK(dqp);
+	spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
 	dqp->q_pincount--;
 	if (dqp->q_pincount == 0) {
 		sv_broadcast(&dqp->q_pinwait);
 	}
-	XFS_DQ_PINUNLOCK(dqp, s);
+	spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
 }
 
 /* ARGSUSED */
@@ -189,8 +187,6 @@
 xfs_qm_dqunpin_wait(
 	xfs_dquot_t	*dqp)
 {
-	SPLDECL(s);
-
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	if (dqp->q_pincount == 0) {
 		return;
@@ -200,9 +196,9 @@
 	 * Give the log a push so we don't wait here too long.
 	 */
 	xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE);
-	s = XFS_DQ_PINLOCK(dqp);
+	spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
 	if (dqp->q_pincount == 0) {
-		XFS_DQ_PINUNLOCK(dqp, s);
+		spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
 		return;
 	}
 	sv_wait(&(dqp->q_pinwait), PINOD,
@@ -216,8 +212,8 @@
  * If so, we want to push it out to help us take this item off the AIL as soon
  * as possible.
  *
- * We must not be holding the AIL_LOCK at this point. Calling incore() to
- * search the buffer cache can be a time consuming thing, and AIL_LOCK is a
+ * We must not be holding the AIL lock at this point. Calling incore() to
+ * search the buffer cache can be a time consuming thing, and AIL lock is a
  * spinlock.
  */
 STATIC void
@@ -322,7 +318,7 @@
 		 * want to do that now since we might sleep in the device
 		 * strategy routine.  We also don't want to grab the buffer lock
 		 * here because we'd like not to call into the buffer cache
-		 * while holding the AIL_LOCK.
+		 * while holding the AIL lock.
 		 * Make sure to only return PUSHBUF if we set pushbuf_flag
 		 * ourselves.  If someone else is doing it then we don't
 		 * want to go to the push routine and duplicate their efforts.
@@ -562,15 +558,14 @@
 	xfs_lsn_t lsn)
 {
 	xfs_qoff_logitem_t	*qfs;
-	SPLDECL(s);
 
 	qfs = qfe->qql_start_lip;
-	AIL_LOCK(qfs->qql_item.li_mountp,s);
+	spin_lock(&qfs->qql_item.li_mountp->m_ail_lock);
 	/*
 	 * Delete the qoff-start logitem from the AIL.
 	 * xfs_trans_delete_ail() drops the AIL lock.
 	 */
-	xfs_trans_delete_ail(qfs->qql_item.li_mountp, (xfs_log_item_t *)qfs, s);
+	xfs_trans_delete_ail(qfs->qql_item.li_mountp, (xfs_log_item_t *)qfs);
 	kmem_free(qfs, sizeof(xfs_qoff_logitem_t));
 	kmem_free(qfe, sizeof(xfs_qoff_logitem_t));
 	return (xfs_lsn_t)-1;
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index d488645..35582fe 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -310,7 +310,6 @@
 	xfs_mount_t	*mp,
 	int		mfsi_flags)
 {
-	unsigned long	s;
 	int		error = 0;
 	uint		sbf;
 
@@ -367,13 +366,13 @@
 
  write_changes:
 	/*
-	 * We actually don't have to acquire the SB_LOCK at all.
+	 * We actually don't have to acquire the m_sb_lock at all.
 	 * This can only be called from mount, and that's single threaded. XXX
 	 */
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	sbf = mp->m_sb.sb_qflags;
 	mp->m_sb.sb_qflags = mp->m_qflags & XFS_MOUNT_QUOTA_ALL;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	if (sbf != (mp->m_qflags & XFS_MOUNT_QUOTA_ALL)) {
 		if (xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS)) {
@@ -1139,7 +1138,7 @@
 		return error;
 	}
 
-	spinlock_init(&qinf->qi_pinlock, "xfs_qinf_pin");
+	spin_lock_init(&qinf->qi_pinlock);
 	xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0);
 	qinf->qi_dqreclaims = 0;
 
@@ -1370,7 +1369,6 @@
 {
 	xfs_trans_t	*tp;
 	int		error;
-	unsigned long	s;
 	int		committed;
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
@@ -1402,7 +1400,7 @@
 	 * sbfields arg may contain fields other than *QUOTINO;
 	 * VERSIONNUM for example.
 	 */
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	if (flags & XFS_QMOPT_SBVERSION) {
 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
 		unsigned oldv = mp->m_sb.sb_versionnum;
@@ -1429,7 +1427,7 @@
 		mp->m_sb.sb_uquotino = (*ip)->i_ino;
 	else
 		mp->m_sb.sb_gquotino = (*ip)->i_ino;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 	xfs_mod_sb(tp, sbfields);
 
 	if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 23ccaa5..baf537c 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -52,8 +52,8 @@
 /*
  * Dquot hashtable constants/threshold values.
  */
-#define XFS_QM_HASHSIZE_LOW		(NBPP / sizeof(xfs_dqhash_t))
-#define XFS_QM_HASHSIZE_HIGH		((NBPP * 4) / sizeof(xfs_dqhash_t))
+#define XFS_QM_HASHSIZE_LOW		(PAGE_SIZE / sizeof(xfs_dqhash_t))
+#define XFS_QM_HASHSIZE_HIGH		((PAGE_SIZE * 4) / sizeof(xfs_dqhash_t))
 
 /*
  * This defines the unit of allocation of dquots.
@@ -106,7 +106,7 @@
 typedef struct xfs_quotainfo {
 	xfs_inode_t	*qi_uquotaip;	 /* user quota inode */
 	xfs_inode_t	*qi_gquotaip;	 /* group quota inode */
-	lock_t		 qi_pinlock;	 /* dquot pinning mutex */
+	spinlock_t	 qi_pinlock;	 /* dquot pinning lock */
 	xfs_dqlist_t	 qi_dqlist;	 /* all dquots in filesys */
 	int		 qi_dqreclaims;	 /* a change here indicates
 					    a removal in the dqlist */
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index ad5579d..2cc5886 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -200,7 +200,6 @@
 	boolean_t		force)
 {
 	uint			dqtype;
-	unsigned long	s;
 	int			error;
 	uint			inactivate_flags;
 	xfs_qoff_logitem_t	*qoffstart;
@@ -237,9 +236,9 @@
 	if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
 		mp->m_qflags &= ~(flags);
 
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		mp->m_sb.sb_qflags = mp->m_qflags;
-		XFS_SB_UNLOCK(mp, s);
+		spin_unlock(&mp->m_sb_lock);
 		mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
 
 		/* XXX what to do if error ? Revert back to old vals incore ? */
@@ -415,7 +414,6 @@
 	uint		flags)
 {
 	int		error;
-	unsigned long	s;
 	uint		qf;
 	uint		accflags;
 	__int64_t	sbflags;
@@ -468,10 +466,10 @@
 	 * Change sb_qflags on disk but not incore mp->qflags
 	 * if this is the root filesystem.
 	 */
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	qf = mp->m_sb.sb_qflags;
 	mp->m_sb.sb_qflags = qf | flags;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	/*
 	 * There's nothing to change if it's the same.
@@ -815,7 +813,6 @@
 {
 	xfs_trans_t	       *tp;
 	int			error;
-	unsigned long	s;
 	xfs_qoff_logitem_t     *qoffi=NULL;
 	uint			oldsbqflag=0;
 
@@ -832,10 +829,10 @@
 	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
 	xfs_trans_log_quotaoff_item(tp, qoffi);
 
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	oldsbqflag = mp->m_sb.sb_qflags;
 	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	xfs_mod_sb(tp, XFS_SB_QFLAGS);
 
@@ -854,9 +851,9 @@
 		 * No one else is modifying sb_qflags, so this is OK.
 		 * We still hold the quotaofflock.
 		 */
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		mp->m_sb.sb_qflags = oldsbqflag;
-		XFS_SB_UNLOCK(mp, s);
+		spin_unlock(&mp->m_sb_lock);
 	}
 	*qoffstartp = qoffi;
 	return (error);
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index f45a49f..c27abef 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -17,7 +17,6 @@
  */
 #include <xfs.h>
 #include "debug.h"
-#include "spin.h"
 
 static char		message[1024];	/* keep it off the stack */
 static DEFINE_SPINLOCK(xfs_err_lock);
@@ -81,3 +80,9 @@
 	printk("Assertion failed: %s, file: %s, line: %d\n", expr, file, line);
 	BUG();
 }
+
+void
+xfs_hex_dump(void *p, int length)
+{
+	print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_OFFSET, 16, 1, p, length, 1);
+}
diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
index 5cf2e86..129067c 100644
--- a/fs/xfs/support/ktrace.c
+++ b/fs/xfs/support/ktrace.c
@@ -21,7 +21,7 @@
 static kmem_zone_t *ktrace_ent_zone;
 static int          ktrace_zentries;
 
-void
+void __init
 ktrace_init(int zentries)
 {
 	ktrace_zentries = zentries;
@@ -36,7 +36,7 @@
 	ASSERT(ktrace_ent_zone);
 }
 
-void
+void __exit
 ktrace_uninit(void)
 {
 	kmem_zone_destroy(ktrace_hdr_zone);
@@ -90,8 +90,6 @@
 		return NULL;
 	}
 
-	spinlock_init(&(ktp->kt_lock), "kt_lock");
-
 	ktp->kt_entries  = ktep;
 	ktp->kt_nentries = nentries;
 	ktp->kt_index    = 0;
@@ -114,8 +112,6 @@
 	if (ktp == (ktrace_t *)NULL)
 		return;
 
-	spinlock_destroy(&ktp->kt_lock);
-
 	/*
 	 * Special treatment for the Vnode trace buffer.
 	 */
diff --git a/fs/xfs/support/ktrace.h b/fs/xfs/support/ktrace.h
index 0d73216..56e72b4 100644
--- a/fs/xfs/support/ktrace.h
+++ b/fs/xfs/support/ktrace.h
@@ -18,8 +18,6 @@
 #ifndef __XFS_SUPPORT_KTRACE_H__
 #define __XFS_SUPPORT_KTRACE_H__
 
-#include <spin.h>
-
 /*
  * Trace buffer entry structure.
  */
@@ -31,7 +29,6 @@
  * Trace buffer header structure.
  */
 typedef struct ktrace {
-	lock_t		kt_lock;	/* mutex to guard counters */
 	int		kt_nentries;	/* number of entries in trace buf */
 	int		kt_index;	/* current index in entries */
 	int		kt_rollover;
diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c
index e157015..493a6ec 100644
--- a/fs/xfs/support/uuid.c
+++ b/fs/xfs/support/uuid.c
@@ -133,7 +133,7 @@
 	mutex_unlock(&uuid_monitor);
 }
 
-void
+void __init
 uuid_init(void)
 {
 	mutex_init(&uuid_monitor);
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index b5a7d92..540e4c9 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -37,7 +37,7 @@
 #define XFS_LOG_TRACE 1
 #define XFS_RW_TRACE 1
 #define XFS_BUF_TRACE 1
-#define XFS_VNODE_TRACE 1
+#define XFS_INODE_TRACE 1
 #define XFS_FILESTREAMS_TRACE 1
 #endif
 
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 5bfb66f..7272fe3 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -392,32 +392,6 @@
 }
 
 /*
- * The access control process to determine the access permission:
- *	if uid == file owner id, use the file owner bits.
- *	if gid == file owner group id, use the file group bits.
- *	scan ACL for a matching user or group, and use matched entry
- *	permission. Use total permissions of all matching group entries,
- *	until all acl entries are exhausted. The final permission produced
- *	by matching acl entry or entries needs to be & with group permission.
- *	if not owner, owning group, or matching entry in ACL, use file
- *	other bits.  
- */
-STATIC int
-xfs_acl_capability_check(
-	mode_t		mode,
-	cred_t		*cr)
-{
-	if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
-		return EACCES;
-	if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
-		return EACCES;
-	if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
-		return EACCES;
-
-	return 0;
-}
-
-/*
  * Note: cr is only used here for the capability check if the ACL test fails.
  *       It is not used to find out the credentials uid or groups etc, as was
  *       done in IRIX. It is assumed that the uid and groups for the current
@@ -438,7 +412,6 @@
 
 	matched.ae_tag = 0;	/* Invalid type */
 	matched.ae_perm = 0;
-	md >>= 6;	/* Normalize the bits for comparison */
 
 	for (i = 0; i < fap->acl_cnt; i++) {
 		/*
@@ -520,7 +493,8 @@
 		break;
 	}
 
-	return xfs_acl_capability_check(md, cr);
+	/* EACCES tells generic_permission to check for capability overrides */
+	return EACCES;
 }
 
 /*
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 34b7d33..332a772 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -75,7 +75,6 @@
 #define _ACL_GET_DEFAULT(pv,pd)	(xfs_acl_vtoacl(pv,NULL,pd) == 0)
 #define _ACL_ACCESS_EXISTS	xfs_acl_vhasacl_access
 #define _ACL_DEFAULT_EXISTS	xfs_acl_vhasacl_default
-#define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
 
 #define _ACL_ALLOC(a)		((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
 #define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
@@ -95,7 +94,6 @@
 #define _ACL_GET_DEFAULT(pv,pd)	(0)
 #define _ACL_ACCESS_EXISTS	(NULL)
 #define _ACL_DEFAULT_EXISTS	(NULL)
-#define _ACL_XFS_IACCESS(i,m,c) (-1)
 #endif
 
 #endif	/* __XFS_ACL_H__ */
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 9381b03..61b292a 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -193,7 +193,7 @@
 	xfs_agino_t	pagi_count;	/* number of allocated inodes */
 	int		pagb_count;	/* pagb slots in use */
 #ifdef __KERNEL__
-	lock_t		pagb_lock;	/* lock for pagb_list */
+	spinlock_t	pagb_lock;	/* lock for pagb_list */
 #endif
 	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
 	atomic_t        pagf_fstrms;    /* # of filestreams active in this AG */
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 012a649..ea6aa60 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2206,7 +2206,7 @@
 			be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
 		pag->pagf_levels[XFS_BTNUM_CNTi] =
 			be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
-		spinlock_init(&pag->pagb_lock, "xfspagb");
+		spin_lock_init(&pag->pagb_lock);
 		pag->pagb_list = kmem_zalloc(XFS_PAGB_NUM_SLOTS *
 					sizeof(xfs_perag_busy_t), KM_SLEEP);
 		pag->pagf_init = 1;
@@ -2500,10 +2500,9 @@
 	xfs_mount_t		*mp;
 	xfs_perag_busy_t	*bsy;
 	int			n;
-	SPLDECL(s);
 
 	mp = tp->t_mountp;
-	s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
+	spin_lock(&mp->m_perag[agno].pagb_lock);
 
 	/* search pagb_list for an open slot */
 	for (bsy = mp->m_perag[agno].pagb_list, n = 0;
@@ -2533,7 +2532,7 @@
 		xfs_trans_set_sync(tp);
 	}
 
-	mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
+	spin_unlock(&mp->m_perag[agno].pagb_lock);
 }
 
 void
@@ -2543,11 +2542,10 @@
 {
 	xfs_mount_t		*mp;
 	xfs_perag_busy_t	*list;
-	SPLDECL(s);
 
 	mp = tp->t_mountp;
 
-	s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
+	spin_lock(&mp->m_perag[agno].pagb_lock);
 	list = mp->m_perag[agno].pagb_list;
 
 	ASSERT(idx < XFS_PAGB_NUM_SLOTS);
@@ -2559,7 +2557,7 @@
 		TRACE_UNBUSY("xfs_alloc_clear_busy", "missing", agno, idx, tp);
 	}
 
-	mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
+	spin_unlock(&mp->m_perag[agno].pagb_lock);
 }
 
 
@@ -2578,11 +2576,10 @@
 	xfs_agblock_t		uend, bend;
 	xfs_lsn_t		lsn;
 	int			cnt;
-	SPLDECL(s);
 
 	mp = tp->t_mountp;
 
-	s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
+	spin_lock(&mp->m_perag[agno].pagb_lock);
 	cnt = mp->m_perag[agno].pagb_count;
 
 	uend = bno + len - 1;
@@ -2615,12 +2612,12 @@
 	if (cnt) {
 		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, n, tp);
 		lsn = bsy->busy_tp->t_commit_lsn;
-		mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
+		spin_unlock(&mp->m_perag[agno].pagb_lock);
 		xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
 	} else {
 		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, n, tp);
 		n = -1;
-		mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
+		spin_unlock(&mp->m_perag[agno].pagb_lock);
 	}
 
 	return n;
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 93fa64d..e58f321 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -929,7 +929,7 @@
  * This leaf block cannot have a "remote" value, we only call this routine
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
-int
+STATIC int
 xfs_attr_leaf_addname(xfs_da_args_t *args)
 {
 	xfs_inode_t *dp;
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 81f45da..eb3815e 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -226,17 +226,15 @@
 STATIC void
 xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
 {
-	unsigned long s;
-
 	if ((mp->m_flags & XFS_MOUNT_ATTR2) &&
 	    !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
 			XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
-			XFS_SB_UNLOCK(mp, s);
+			spin_unlock(&mp->m_sb_lock);
 			xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
 		} else
-			XFS_SB_UNLOCK(mp, s);
+			spin_unlock(&mp->m_sb_lock);
 	}
 }
 
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index fab0b6d..4822884 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -25,109 +25,6 @@
  * XFS bit manipulation routines, used in non-realtime code.
  */
 
-#ifndef HAVE_ARCH_HIGHBIT
-/*
- * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
- */
-static const char xfs_highbit[256] = {
-       -1, 0, 1, 1, 2, 2, 2, 2,			/* 00 .. 07 */
-	3, 3, 3, 3, 3, 3, 3, 3,			/* 08 .. 0f */
-	4, 4, 4, 4, 4, 4, 4, 4,			/* 10 .. 17 */
-	4, 4, 4, 4, 4, 4, 4, 4,			/* 18 .. 1f */
-	5, 5, 5, 5, 5, 5, 5, 5,			/* 20 .. 27 */
-	5, 5, 5, 5, 5, 5, 5, 5,			/* 28 .. 2f */
-	5, 5, 5, 5, 5, 5, 5, 5,			/* 30 .. 37 */
-	5, 5, 5, 5, 5, 5, 5, 5,			/* 38 .. 3f */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 40 .. 47 */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 48 .. 4f */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 50 .. 57 */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 58 .. 5f */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 60 .. 67 */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 68 .. 6f */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 70 .. 77 */
-	6, 6, 6, 6, 6, 6, 6, 6,			/* 78 .. 7f */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* 80 .. 87 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* 88 .. 8f */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* 90 .. 97 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* 98 .. 9f */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* a0 .. a7 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* a8 .. af */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* b0 .. b7 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* b8 .. bf */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* c0 .. c7 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* c8 .. cf */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* d0 .. d7 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* d8 .. df */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* e0 .. e7 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* e8 .. ef */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* f0 .. f7 */
-	7, 7, 7, 7, 7, 7, 7, 7,			/* f8 .. ff */
-};
-#endif
-
-/*
- * xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
- */
-inline int
-xfs_highbit32(
-	__uint32_t	v)
-{
-#ifdef HAVE_ARCH_HIGHBIT
-	return highbit32(v);
-#else
-	int		i;
-
-	if (v & 0xffff0000)
-		if (v & 0xff000000)
-			i = 24;
-		else
-			i = 16;
-	else if (v & 0x0000ffff)
-		if (v & 0x0000ff00)
-			i = 8;
-		else
-			i = 0;
-	else
-		return -1;
-	return i + xfs_highbit[(v >> i) & 0xff];
-#endif
-}
-
-/*
- * xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set.
- */
-int
-xfs_lowbit64(
-	__uint64_t	v)
-{
-	__uint32_t	w = (__uint32_t)v;
-	int		n = 0;
-
-	if (w) {	/* lower bits */
-		n = ffs(w);
-	} else {	/* upper bits */
-		w = (__uint32_t)(v >> 32);
-		if (w && (n = ffs(w)))
-			n += 32;
-	}
-	return n - 1;
-}
-
-/*
- * xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set.
- */
-int
-xfs_highbit64(
-	__uint64_t	v)
-{
-	__uint32_t	h = (__uint32_t)(v >> 32);
-
-	if (h)
-		return xfs_highbit32(h) + 32;
-	return xfs_highbit32((__uint32_t)v);
-}
-
-
 /*
  * Return whether bitmap is empty.
  * Size is number of words in the bitmap, which is padded to word boundary
diff --git a/fs/xfs/xfs_bit.h b/fs/xfs/xfs_bit.h
index 082641a..325a007 100644
--- a/fs/xfs/xfs_bit.h
+++ b/fs/xfs/xfs_bit.h
@@ -47,13 +47,30 @@
 }
 
 /* Get high bit set out of 32-bit argument, -1 if none set */
-extern int xfs_highbit32(__uint32_t v);
-
-/* Get low bit set out of 64-bit argument, -1 if none set */
-extern int xfs_lowbit64(__uint64_t v);
+static inline int xfs_highbit32(__uint32_t v)
+{
+	return fls(v) - 1;
+}
 
 /* Get high bit set out of 64-bit argument, -1 if none set */
-extern int xfs_highbit64(__uint64_t);
+static inline int xfs_highbit64(__uint64_t v)
+{
+	return fls64(v) - 1;
+}
+
+/* Get low bit set out of 32-bit argument, -1 if none set */
+static inline int xfs_lowbit32(__uint32_t v)
+{
+	__uint32_t t = v;
+	return (t) ? find_first_bit((unsigned long *)&t, 32) : -1;
+}
+
+/* Get low bit set out of 64-bit argument, -1 if none set */
+static inline int xfs_lowbit64(__uint64_t v)
+{
+	__uint64_t t = v;
+	return (t) ? find_first_bit((unsigned long *)&t, 64) : -1;
+}
 
 /* Return whether bitmap is empty (1 == empty) */
 extern int xfs_bitmap_empty(uint *map, uint size);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 2e9b34b..1c0a5a5 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2830,11 +2830,11 @@
 		args.prod = align;
 		if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
 			args.mod = (xfs_extlen_t)(args.prod - args.mod);
-	} else if (mp->m_sb.sb_blocksize >= NBPP) {
+	} else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) {
 		args.prod = 1;
 		args.mod = 0;
 	} else {
-		args.prod = NBPP >> mp->m_sb.sb_blocklog;
+		args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog;
 		if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
 			args.mod = (xfs_extlen_t)(args.prod - args.mod);
 	}
@@ -2969,7 +2969,7 @@
 xfs_bmap_alloc(
 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
 {
-	if ((ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata)
+	if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)
 		return xfs_bmap_rtalloc(ap);
 	return xfs_bmap_btalloc(ap);
 }
@@ -3096,8 +3096,7 @@
 		/*
 		 * Realtime allocation.  Free it and record di_nblocks update.
 		 */
-		if (whichfork == XFS_DATA_FORK &&
-		    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
+		if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
 			xfs_fsblock_t	bno;
 			xfs_filblks_t	len;
 
@@ -3956,7 +3955,6 @@
 	xfs_bmap_free_t		flist;		/* freed extent records */
 	xfs_mount_t		*mp;		/* mount structure */
 	xfs_trans_t		*tp;		/* transaction pointer */
-	unsigned long		s;		/* spinlock spl value */
 	int			blks;		/* space reservation */
 	int			version = 1;	/* superblock attr version */
 	int			committed;	/* xaction was committed */
@@ -4053,7 +4051,7 @@
 	   (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2)) {
 		__int64_t sbfields = 0;
 
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) {
 			XFS_SB_VERSION_ADDATTR(&mp->m_sb);
 			sbfields |= XFS_SB_VERSIONNUM;
@@ -4063,10 +4061,10 @@
 			sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
 		}
 		if (sbfields) {
-			XFS_SB_UNLOCK(mp, s);
+			spin_unlock(&mp->m_sb_lock);
 			xfs_mod_sb(tp, sbfields);
 		} else
-			XFS_SB_UNLOCK(mp, s);
+			spin_unlock(&mp->m_sb_lock);
 	}
 	if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
 		goto error2;
@@ -6394,7 +6392,7 @@
  * Recursively walks each level of a btree
  * to count total fsblocks is use.
  */
-int                                     /* error */
+STATIC int                                     /* error */
 xfs_bmap_count_tree(
 	xfs_mount_t     *mp,            /* file system mount point */
 	xfs_trans_t     *tp,            /* transaction pointer */
@@ -6470,7 +6468,7 @@
 /*
  * Count leaf blocks given a range of extent records.
  */
-int
+STATIC int
 xfs_bmap_count_leaves(
 	xfs_ifork_t		*ifp,
 	xfs_extnum_t		idx,
@@ -6490,7 +6488,7 @@
  * Count leaf blocks given a range of extent records originally
  * in btree format.
  */
-int
+STATIC int
 xfs_bmap_disk_count_leaves(
 	xfs_extnum_t		idx,
 	xfs_bmbt_block_t	*block,
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 68267d7..87224b7 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -25,6 +25,8 @@
 struct xfs_mount;
 struct xfs_trans;
 
+extern kmem_zone_t	*xfs_bmap_free_item_zone;
+
 /*
  * DELTA: describe a change to the in-core extent list.
  *
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 32b49ec..c4181d8 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2062,8 +2062,7 @@
 				pcur->bc_private.b.allocated;
 			pcur->bc_private.b.allocated = 0;
 			ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) ||
-			       (cur->bc_private.b.ip->i_d.di_flags &
-				XFS_DIFLAG_REALTIME));
+			       XFS_IS_REALTIME_INODE(cur->bc_private.b.ip));
 			cur->bc_private.b.firstblock =
 				pcur->bc_private.b.firstblock;
 			ASSERT(cur->bc_private.b.flist ==
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 6e40a0a..7440b78 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -24,6 +24,8 @@
 struct xfs_mount;
 struct xfs_trans;
 
+extern kmem_zone_t	*xfs_btree_cur_zone;
+
 /*
  * This nonsense is to make -wlint happy.
  */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index c8f2c28..63debd1 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -378,7 +378,6 @@
 	xfs_mount_t	*mp;
 	xfs_buf_t	*bp;
 	int		freed;
-	SPLDECL(s);
 
 	bp = bip->bli_buf;
 	ASSERT(bp != NULL);
@@ -409,8 +408,8 @@
 			XFS_BUF_SET_FSPRIVATE(bp, NULL);
 			XFS_BUF_CLR_IODONE_FUNC(bp);
 		} else {
-			AIL_LOCK(mp,s);
-			xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip, s);
+			spin_lock(&mp->m_ail_lock);
+			xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip);
 			xfs_buf_item_relse(bp);
 			ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL);
 		}
@@ -1113,7 +1112,6 @@
 	xfs_buf_log_item_t	*bip)
 {
 	struct xfs_mount	*mp;
-	SPLDECL(s);
 
 	ASSERT(bip->bli_buf == bp);
 
@@ -1128,11 +1126,11 @@
 	 *
 	 * Either way, AIL is useless if we're forcing a shutdown.
 	 */
-	AIL_LOCK(mp,s);
+	spin_lock(&mp->m_ail_lock);
 	/*
 	 * xfs_trans_delete_ail() drops the AIL lock.
 	 */
-	xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip, s);
+	xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip);
 
 #ifdef XFS_TRANS_DEBUG
 	kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp));
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index d7e1361..5a41c34 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -18,6 +18,8 @@
 #ifndef	__XFS_BUF_ITEM_H__
 #define	__XFS_BUF_ITEM_H__
 
+extern kmem_zone_t	*xfs_buf_item_zone;
+
 /*
  * This is the structure used to lay out a buf log item in the
  * log.  The data map describes which 128 byte chunks of the buffer
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 26d09e2..1b44684 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -2218,7 +2218,7 @@
 
 #ifdef XFS_DABUF_DEBUG
 xfs_dabuf_t	*xfs_dabuf_global_list;
-lock_t		xfs_dabuf_global_lock;
+spinlock_t	xfs_dabuf_global_lock;
 #endif
 
 /*
@@ -2264,10 +2264,9 @@
 	}
 #ifdef XFS_DABUF_DEBUG
 	{
-		SPLDECL(s);
 		xfs_dabuf_t	*p;
 
-		s = mutex_spinlock(&xfs_dabuf_global_lock);
+		spin_lock(&xfs_dabuf_global_lock);
 		for (p = xfs_dabuf_global_list; p; p = p->next) {
 			ASSERT(p->blkno != dabuf->blkno ||
 			       p->target != dabuf->target);
@@ -2277,7 +2276,7 @@
 			xfs_dabuf_global_list->prev = dabuf;
 		dabuf->next = xfs_dabuf_global_list;
 		xfs_dabuf_global_list = dabuf;
-		mutex_spinunlock(&xfs_dabuf_global_lock, s);
+		spin_unlock(&xfs_dabuf_global_lock);
 	}
 #endif
 	return dabuf;
@@ -2319,16 +2318,14 @@
 		kmem_free(dabuf->data, BBTOB(dabuf->bbcount));
 #ifdef XFS_DABUF_DEBUG
 	{
-		SPLDECL(s);
-
-		s = mutex_spinlock(&xfs_dabuf_global_lock);
+		spin_lock(&xfs_dabuf_global_lock);
 		if (dabuf->prev)
 			dabuf->prev->next = dabuf->next;
 		else
 			xfs_dabuf_global_list = dabuf->next;
 		if (dabuf->next)
 			dabuf->next->prev = dabuf->prev;
-		mutex_spinunlock(&xfs_dabuf_global_lock, s);
+		spin_unlock(&xfs_dabuf_global_lock);
 	}
 	memset(dabuf, 0, XFS_DA_BUF_SIZE(dabuf->nbuf));
 #endif
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 44dabf0..7facf86 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -260,6 +260,7 @@
 xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf);
 
 extern struct kmem_zone *xfs_da_state_zone;
+extern struct kmem_zone *xfs_dabuf_zone;
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_DA_BTREE_H__ */
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 584f1ae..3f53fad 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -52,76 +52,72 @@
 	xfs_swapext_t	__user *sxu)
 {
 	xfs_swapext_t	*sxp;
-	xfs_inode_t     *ip=NULL, *tip=NULL;
-	xfs_mount_t     *mp;
-	struct file	*fp = NULL, *tfp = NULL;
-	bhv_vnode_t	*vp, *tvp;
+	xfs_inode_t     *ip, *tip;
+	struct file	*file, *target_file;
 	int		error = 0;
 
 	sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
 	if (!sxp) {
 		error = XFS_ERROR(ENOMEM);
-		goto error0;
+		goto out;
 	}
 
 	if (copy_from_user(sxp, sxu, sizeof(xfs_swapext_t))) {
 		error = XFS_ERROR(EFAULT);
-		goto error0;
+		goto out_free_sxp;
 	}
 
 	/* Pull information for the target fd */
-	if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) ||
-	    ((vp = vn_from_inode(fp->f_path.dentry->d_inode)) == NULL))  {
+	file = fget((int)sxp->sx_fdtarget);
+	if (!file) {
 		error = XFS_ERROR(EINVAL);
-		goto error0;
+		goto out_free_sxp;
 	}
 
-	ip = xfs_vtoi(vp);
-	if (ip == NULL) {
+	if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) {
 		error = XFS_ERROR(EBADF);
-		goto error0;
+		goto out_put_file;
 	}
 
-	if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) ||
-	    ((tvp = vn_from_inode(tfp->f_path.dentry->d_inode)) == NULL)) {
+	target_file = fget((int)sxp->sx_fdtmp);
+	if (!target_file) {
 		error = XFS_ERROR(EINVAL);
-		goto error0;
+		goto out_put_file;
 	}
 
-	tip = xfs_vtoi(tvp);
-	if (tip == NULL) {
+	if (!(target_file->f_mode & FMODE_WRITE) ||
+	    (target_file->f_flags & O_APPEND)) {
 		error = XFS_ERROR(EBADF);
-		goto error0;
+		goto out_put_target_file;
 	}
 
+	ip = XFS_I(file->f_path.dentry->d_inode);
+	tip = XFS_I(target_file->f_path.dentry->d_inode);
+
 	if (ip->i_mount != tip->i_mount) {
-		error =  XFS_ERROR(EINVAL);
-		goto error0;
+		error = XFS_ERROR(EINVAL);
+		goto out_put_target_file;
 	}
 
 	if (ip->i_ino == tip->i_ino) {
-		error =  XFS_ERROR(EINVAL);
-		goto error0;
+		error = XFS_ERROR(EINVAL);
+		goto out_put_target_file;
 	}
 
-	mp = ip->i_mount;
-
-	if (XFS_FORCED_SHUTDOWN(mp)) {
-		error =  XFS_ERROR(EIO);
-		goto error0;
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+		error = XFS_ERROR(EIO);
+		goto out_put_target_file;
 	}
 
-	error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp);
+	error = xfs_swap_extents(ip, tip, sxp);
 
- error0:
-	if (fp != NULL)
-		fput(fp);
-	if (tfp != NULL)
-		fput(tfp);
-
-	if (sxp != NULL)
-		kmem_free(sxp, sizeof(xfs_swapext_t));
-
+ out_put_target_file:
+	fput(target_file);
+ out_put_file:
+	fput(file);
+ out_free_sxp:
+	kmem_free(sxp, sizeof(xfs_swapext_t));
+ out:
 	return error;
 }
 
@@ -169,15 +165,6 @@
 	xfs_lock_inodes(ips, 2, 0, lock_flags);
 	locked = 1;
 
-	/* Check permissions */
-	error = xfs_iaccess(ip, S_IWUSR, NULL);
-	if (error)
-		goto error0;
-
-	error = xfs_iaccess(tip, S_IWUSR, NULL);
-	if (error)
-		goto error0;
-
 	/* Verify that both files have the same format */
 	if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
 		error = XFS_ERROR(EINVAL);
@@ -185,8 +172,7 @@
 	}
 
 	/* Verify both files are either real-time or non-realtime */
-	if ((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) !=
-	    (tip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
+	if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) {
 		error = XFS_ERROR(EINVAL);
 		goto error0;
 	}
@@ -199,7 +185,7 @@
 	}
 
 	if (VN_CACHED(tvp) != 0) {
-		xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
+		xfs_inval_cached_trace(tip, 0, -1, 0, -1);
 		error = xfs_flushinval_pages(tip, 0, -1,
 				FI_REMAPF_LOCKED);
 		if (error)
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index dedd7135..c9065ea 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -171,69 +171,35 @@
 /*
  * Inode data & attribute fork sizes, per inode.
  */
-#define XFS_CFORK_Q(dcp)                    ((dcp)->di_forkoff != 0)
-#define	XFS_CFORK_Q_DISK(dcp)		    ((dcp)->di_forkoff != 0)
-
-#define XFS_CFORK_BOFF(dcp)                 ((int)((dcp)->di_forkoff << 3))
-#define	XFS_CFORK_BOFF_DISK(dcp)	    ((int)((dcp)->di_forkoff << 3))
-
-#define	XFS_CFORK_DSIZE_DISK(dcp,mp) \
-	(XFS_CFORK_Q_DISK(dcp) ? XFS_CFORK_BOFF_DISK(dcp) : XFS_LITINO(mp))
-#define XFS_CFORK_DSIZE(dcp,mp) \
-	(XFS_CFORK_Q(dcp) ? XFS_CFORK_BOFF(dcp) : XFS_LITINO(mp))
-
-#define	XFS_CFORK_ASIZE_DISK(dcp,mp) \
-	(XFS_CFORK_Q_DISK(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF_DISK(dcp) : 0)
-#define XFS_CFORK_ASIZE(dcp,mp) \
-	(XFS_CFORK_Q(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF(dcp) : 0)
-
-#define	XFS_CFORK_SIZE_DISK(dcp,mp,w) \
-	((w) == XFS_DATA_FORK ? \
-		XFS_CFORK_DSIZE_DISK(dcp, mp) : \
-	 	XFS_CFORK_ASIZE_DISK(dcp, mp))
-#define XFS_CFORK_SIZE(dcp,mp,w) \
-	((w) == XFS_DATA_FORK ? \
-		XFS_CFORK_DSIZE(dcp, mp) : XFS_CFORK_ASIZE(dcp, mp))
+#define XFS_DFORK_Q(dip)		((dip)->di_core.di_forkoff != 0)
+#define XFS_DFORK_BOFF(dip)		((int)((dip)->di_core.di_forkoff << 3))
 
 #define XFS_DFORK_DSIZE(dip,mp) \
-	XFS_CFORK_DSIZE_DISK(&(dip)->di_core, mp)
-#define XFS_DFORK_DSIZE_HOST(dip,mp) \
-	XFS_CFORK_DSIZE(&(dip)->di_core, mp)
+	(XFS_DFORK_Q(dip) ? \
+		XFS_DFORK_BOFF(dip) : \
+		XFS_LITINO(mp))
 #define XFS_DFORK_ASIZE(dip,mp) \
-	XFS_CFORK_ASIZE_DISK(&(dip)->di_core, mp)
-#define XFS_DFORK_ASIZE_HOST(dip,mp) \
-	XFS_CFORK_ASIZE(&(dip)->di_core, mp)
-#define	XFS_DFORK_SIZE(dip,mp,w) \
-	XFS_CFORK_SIZE_DISK(&(dip)->di_core, mp, w)
-#define	XFS_DFORK_SIZE_HOST(dip,mp,w) \
-	XFS_CFORK_SIZE(&(dip)->di_core, mp, w)
+	(XFS_DFORK_Q(dip) ? \
+		XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : \
+		0)
+#define XFS_DFORK_SIZE(dip,mp,w) \
+	((w) == XFS_DATA_FORK ? \
+		XFS_DFORK_DSIZE(dip, mp) : \
+		XFS_DFORK_ASIZE(dip, mp))
 
-#define	XFS_DFORK_Q(dip)                    XFS_CFORK_Q_DISK(&(dip)->di_core)
-#define	XFS_DFORK_BOFF(dip)		    XFS_CFORK_BOFF_DISK(&(dip)->di_core)
-#define	XFS_DFORK_DPTR(dip)		    ((dip)->di_u.di_c)
-#define	XFS_DFORK_APTR(dip)	\
+#define XFS_DFORK_DPTR(dip)		    ((dip)->di_u.di_c)
+#define XFS_DFORK_APTR(dip)	\
 	((dip)->di_u.di_c + XFS_DFORK_BOFF(dip))
-#define	XFS_DFORK_PTR(dip,w)	\
+#define XFS_DFORK_PTR(dip,w)	\
 	((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip))
-#define	XFS_CFORK_FORMAT(dcp,w)	\
-	((w) == XFS_DATA_FORK ? (dcp)->di_format : (dcp)->di_aformat)
-#define	XFS_CFORK_FMT_SET(dcp,w,n) \
+#define XFS_DFORK_FORMAT(dip,w) \
 	((w) == XFS_DATA_FORK ? \
-		((dcp)->di_format = (n)) : ((dcp)->di_aformat = (n)))
-#define	XFS_DFORK_FORMAT(dip,w) XFS_CFORK_FORMAT(&(dip)->di_core, w)
-
-#define	XFS_CFORK_NEXTENTS_DISK(dcp,w) \
+		(dip)->di_core.di_format : \
+		(dip)->di_core.di_aformat)
+#define XFS_DFORK_NEXTENTS(dip,w) \
 	((w) == XFS_DATA_FORK ? \
-	 	be32_to_cpu((dcp)->di_nextents) : \
-	 	be16_to_cpu((dcp)->di_anextents))
-#define XFS_CFORK_NEXTENTS(dcp,w) \
-	((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
-#define	XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
-#define	XFS_DFORK_NEXTENTS_HOST(dip,w) XFS_CFORK_NEXTENTS(&(dip)->di_core, w)
-
-#define	XFS_CFORK_NEXT_SET(dcp,w,n) \
-	((w) == XFS_DATA_FORK ? \
-		((dcp)->di_nextents = (n)) : ((dcp)->di_anextents = (n)))
+	 	be32_to_cpu((dip)->di_core.di_nextents) : \
+	 	be16_to_cpu((dip)->di_core.di_anextents))
 
 #define	XFS_BUF_TO_DINODE(bp)	((xfs_dinode_t *)XFS_BUF_PTR(bp))
 
@@ -273,6 +239,12 @@
 #define XFS_DIFLAG_NODEFRAG      (1 << XFS_DIFLAG_NODEFRAG_BIT)
 #define XFS_DIFLAG_FILESTREAM    (1 << XFS_DIFLAG_FILESTREAM_BIT)
 
+#ifdef CONFIG_XFS_RT
+#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME)
+#else
+#define XFS_IS_REALTIME_INODE(ip) (0)
+#endif
+
 #define XFS_DIFLAG_ANY \
 	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
 	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index b0f1ee8..be7c425 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -42,6 +42,7 @@
 #include "xfs_dir2_node.h"
 #include "xfs_dir2_trace.h"
 #include "xfs_error.h"
+#include "xfs_vnodeops.h"
 
 
 void
@@ -301,7 +302,7 @@
 	int		rval;		/* return value */
 	int		v;		/* type-checking value */
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 		return XFS_ERROR(EIO);
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index a4634d9..05e5365 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -230,37 +230,6 @@
 	}
 }
 
-STATIC void
-xfs_hex_dump(void *p, int length)
-{
-	__uint8_t *uip = (__uint8_t*)p;
-	int	i;
-	char	sbuf[128], *s;
-
-	s = sbuf;
-	*s = '\0';
-	for (i=0; i<length; i++, uip++) {
-		if ((i % 16) == 0) {
-			if (*s != '\0')
-				cmn_err(CE_ALERT, "%s\n", sbuf);
-			s = sbuf;
-			sprintf(s, "0x%x: ", i);
-			while( *s != '\0')
-				s++;
-		}
-		sprintf(s, "%02x ", *uip);
-
-		/*
-		 * the kernel sprintf is a void; user sprintf returns
-		 * the sprintf'ed string's length.  Find the new end-
-		 * of-string
-		 */
-		while( *s != '\0')
-			s++;
-	}
-	cmn_err(CE_ALERT, "%s\n", sbuf);
-}
-
 void
 xfs_corruption_error(
 	char		*tag,
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 10e9d96..6490d2a 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -174,6 +174,8 @@
 /* PRINTFLIKE3 */
 extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
 
+extern void xfs_hex_dump(void *p, int length);
+
 #define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
 	xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args)
 
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index f938a51..132bd07 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -110,19 +110,18 @@
 xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
 {
 	xfs_mount_t	*mp;
-	SPLDECL(s);
 
 	mp = efip->efi_item.li_mountp;
-	AIL_LOCK(mp, s);
+	spin_lock(&mp->m_ail_lock);
 	if (efip->efi_flags & XFS_EFI_CANCELED) {
 		/*
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
-		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
+		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip);
 		xfs_efi_item_free(efip);
 	} else {
 		efip->efi_flags |= XFS_EFI_COMMITTED;
-		AIL_UNLOCK(mp, s);
+		spin_unlock(&mp->m_ail_lock);
 	}
 }
 
@@ -138,10 +137,9 @@
 {
 	xfs_mount_t	*mp;
 	xfs_log_item_desc_t	*lidp;
-	SPLDECL(s);
 
 	mp = efip->efi_item.li_mountp;
-	AIL_LOCK(mp, s);
+	spin_lock(&mp->m_ail_lock);
 	if (efip->efi_flags & XFS_EFI_CANCELED) {
 		/*
 		 * free the xaction descriptor pointing to this item
@@ -152,11 +150,11 @@
 		 * pull the item off the AIL.
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
-		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
+		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip);
 		xfs_efi_item_free(efip);
 	} else {
 		efip->efi_flags |= XFS_EFI_COMMITTED;
-		AIL_UNLOCK(mp, s);
+		spin_unlock(&mp->m_ail_lock);
 	}
 }
 
@@ -350,13 +348,12 @@
 {
 	xfs_mount_t	*mp;
 	int		extents_left;
-	SPLDECL(s);
 
 	mp = efip->efi_item.li_mountp;
 	ASSERT(efip->efi_next_extent > 0);
 	ASSERT(efip->efi_flags & XFS_EFI_COMMITTED);
 
-	AIL_LOCK(mp, s);
+	spin_lock(&mp->m_ail_lock);
 	ASSERT(efip->efi_next_extent >= nextents);
 	efip->efi_next_extent -= nextents;
 	extents_left = efip->efi_next_extent;
@@ -364,10 +361,10 @@
 		/*
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
-		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
+		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip);
 		xfs_efi_item_free(efip);
 	} else {
-		AIL_UNLOCK(mp, s);
+		spin_unlock(&mp->m_ail_lock);
 	}
 }
 
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 36d8f6a..eb03eab 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -348,7 +348,7 @@
 }
 
 /* xfs_fstrm_free_func(): callback for freeing cached stream items. */
-void
+STATIC void
 xfs_fstrm_free_func(
 	unsigned long	ino,
 	void		*data)
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index aab9662..3bed643 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -419,9 +419,13 @@
 /*
  * ioctl commands that are used by Linux filesystems
  */
-#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
-#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
-#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
+#define XFS_IOC_GETXFLAGS	FS_IOC_GETFLAGS
+#define XFS_IOC_SETXFLAGS	FS_IOC_SETFLAGS
+#define XFS_IOC_GETVERSION	FS_IOC_GETVERSION
+/* 32-bit compat counterparts */
+#define XFS_IOC32_GETXFLAGS	FS_IOC32_GETFLAGS
+#define XFS_IOC32_SETXFLAGS	FS_IOC32_SETFLAGS
+#define XFS_IOC32_GETVERSION	FS_IOC32_GETVERSION
 
 /*
  * ioctl commands that replace IRIX fcntl()'s
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index c92d5b8..b8de7f3 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -462,15 +462,13 @@
 	xfs_mount_t		*mp,
 	xfs_fsop_counts_t	*cnt)
 {
-	unsigned long	s;
-
 	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
 	cnt->freertx = mp->m_sb.sb_frextents;
 	cnt->freeino = mp->m_sb.sb_ifree;
 	cnt->allocino = mp->m_sb.sb_icount;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 	return 0;
 }
 
@@ -497,7 +495,6 @@
 {
 	__int64_t		lcounter, delta, fdblks_delta;
 	__uint64_t		request;
-	unsigned long		s;
 
 	/* If inval is null, report current values and return */
 	if (inval == (__uint64_t *)NULL) {
@@ -515,7 +512,7 @@
 	 * problem. we needto work out if we are freeing or allocation
 	 * blocks first, then we can do the modification as necessary.
 	 *
-	 * We do this under the XFS_SB_LOCK so that if we are near
+	 * We do this under the m_sb_lock so that if we are near
 	 * ENOSPC, we will hold out any changes while we work out
 	 * what to do. This means that the amount of free space can
 	 * change while we do this, so we need to retry if we end up
@@ -526,7 +523,7 @@
 	 * enabled, disabled or even compiled in....
 	 */
 retry:
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED);
 
 	/*
@@ -569,7 +566,7 @@
 		outval->resblks = mp->m_resblks;
 		outval->resblks_avail = mp->m_resblks_avail;
 	}
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	if (fdblks_delta) {
 		/*
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index bf8e9af..8efc4a5 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -81,8 +81,6 @@
 #define	XFS_INOBT_MASK(i)		((xfs_inofree_t)1 << (i))
 #define	XFS_INOBT_IS_FREE(rp,i)		\
 		(((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
-#define	XFS_INOBT_IS_FREE_DISK(rp,i)	\
-		((be64_to_cpu((rp)->ir_free) & XFS_INOBT_MASK(i)) != 0)
 #define	XFS_INOBT_SET_FREE(rp,i)	((rp)->ir_free |= XFS_INOBT_MASK(i))
 #define	XFS_INOBT_CLR_FREE(rp,i)	((rp)->ir_free &= ~XFS_INOBT_MASK(i))
 
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index fb69ef1..f01b076 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -65,7 +65,7 @@
  */
 STATIC int
 xfs_iget_core(
-	bhv_vnode_t	*vp,
+	struct inode	*inode,
 	xfs_mount_t	*mp,
 	xfs_trans_t	*tp,
 	xfs_ino_t	ino,
@@ -74,9 +74,9 @@
 	xfs_inode_t	**ipp,
 	xfs_daddr_t	bno)
 {
+	struct inode	*old_inode;
 	xfs_inode_t	*ip;
 	xfs_inode_t	*iq;
-	bhv_vnode_t	*inode_vp;
 	int		error;
 	xfs_icluster_t	*icl, *new_icl = NULL;
 	unsigned long	first_index, mask;
@@ -111,8 +111,8 @@
 			goto again;
 		}
 
-		inode_vp = XFS_ITOV_NULL(ip);
-		if (inode_vp == NULL) {
+		old_inode = ip->i_vnode;
+		if (old_inode == NULL) {
 			/*
 			 * If IRECLAIM is set this inode is
 			 * on its way out of the system,
@@ -140,28 +140,9 @@
 				return ENOENT;
 			}
 
-			/*
-			 * There may be transactions sitting in the
-			 * incore log buffers or being flushed to disk
-			 * at this time.  We can't clear the
-			 * XFS_IRECLAIMABLE flag until these
-			 * transactions have hit the disk, otherwise we
-			 * will void the guarantee the flag provides
-			 * xfs_iunpin()
-			 */
-			if (xfs_ipincount(ip)) {
-				read_unlock(&pag->pag_ici_lock);
-				xfs_log_force(mp, 0,
-					XFS_LOG_FORCE|XFS_LOG_SYNC);
-				XFS_STATS_INC(xs_ig_frecycle);
-				goto again;
-			}
-
-			vn_trace_exit(ip, "xfs_iget.alloc",
-				(inst_t *)__return_address);
+			xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
 
 			XFS_STATS_INC(xs_ig_found);
-
 			xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
 			read_unlock(&pag->pag_ici_lock);
 
@@ -171,13 +152,11 @@
 
 			goto finish_inode;
 
-		} else if (vp != inode_vp) {
-			struct inode *inode = vn_to_inode(inode_vp);
-
+		} else if (inode != old_inode) {
 			/* The inode is being torn down, pause and
 			 * try again.
 			 */
-			if (inode->i_state & (I_FREEING | I_CLEAR)) {
+			if (old_inode->i_state & (I_FREEING | I_CLEAR)) {
 				read_unlock(&pag->pag_ici_lock);
 				delay(1);
 				XFS_STATS_INC(xs_ig_frecycle);
@@ -190,7 +169,7 @@
 */
 			cmn_err(CE_PANIC,
 		"xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
-					inode_vp, vp);
+					old_inode, inode);
 		}
 
 		/*
@@ -200,20 +179,16 @@
 		XFS_STATS_INC(xs_ig_found);
 
 finish_inode:
-		if (ip->i_d.di_mode == 0) {
-			if (!(flags & XFS_IGET_CREATE)) {
-				xfs_put_perag(mp, pag);
-				return ENOENT;
-			}
-			xfs_iocore_inode_reinit(ip);
+		if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
+			xfs_put_perag(mp, pag);
+			return ENOENT;
 		}
 
 		if (lock_flags != 0)
 			xfs_ilock(ip, lock_flags);
 
 		xfs_iflags_clear(ip, XFS_ISTALE);
-		vn_trace_exit(ip, "xfs_iget.found",
-					(inst_t *)__return_address);
+		xfs_itrace_exit_tag(ip, "xfs_iget.found");
 		goto return_ip;
 	}
 
@@ -234,10 +209,16 @@
 		return error;
 	}
 
-	vn_trace_exit(ip, "xfs_iget.alloc", (inst_t *)__return_address);
+	xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
 
-	xfs_inode_lock_init(ip, vp);
-	xfs_iocore_inode_init(ip);
+
+	mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
+		     "xfsino", ip->i_ino);
+	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+	init_waitqueue_head(&ip->i_ipin_wait);
+	atomic_set(&ip->i_pincount, 0);
+	initnsema(&ip->i_flock, 1, "xfsfino");
+
 	if (lock_flags)
 		xfs_ilock(ip, lock_flags);
 
@@ -333,9 +314,6 @@
 	ASSERT(ip->i_df.if_ext_max ==
 	       XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
 
-	ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
-	       ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
-
 	xfs_iflags_set(ip, XFS_IMODIFIED);
 	*ipp = ip;
 
@@ -343,7 +321,7 @@
 	 * If we have a real type for an on-disk inode, we can set ops(&unlock)
 	 * now.	 If it's a new inode being created, xfs_ialloc will handle it.
 	 */
-	xfs_initialize_vnode(mp, vp, ip);
+	xfs_initialize_vnode(mp, inode, ip);
 	return 0;
 }
 
@@ -363,69 +341,58 @@
 	xfs_daddr_t	bno)
 {
 	struct inode	*inode;
-	bhv_vnode_t	*vp = NULL;
+	xfs_inode_t	*ip;
 	int		error;
 
 	XFS_STATS_INC(xs_ig_attempts);
 
 retry:
 	inode = iget_locked(mp->m_super, ino);
-	if (inode) {
-		xfs_inode_t	*ip;
+	if (!inode)
+		/* If we got no inode we are out of memory */
+		return ENOMEM;
 
-		vp = vn_from_inode(inode);
-		if (inode->i_state & I_NEW) {
-			vn_initialize(inode);
-			error = xfs_iget_core(vp, mp, tp, ino, flags,
-					lock_flags, ipp, bno);
-			if (error) {
-				vn_mark_bad(vp);
-				if (inode->i_state & I_NEW)
-					unlock_new_inode(inode);
-				iput(inode);
-			}
-		} else {
-			/*
-			 * If the inode is not fully constructed due to
-			 * filehandle mismatches wait for the inode to go
-			 * away and try again.
-			 *
-			 * iget_locked will call __wait_on_freeing_inode
-			 * to wait for the inode to go away.
-			 */
-			if (is_bad_inode(inode) ||
-			    ((ip = xfs_vtoi(vp)) == NULL)) {
-				iput(inode);
-				delay(1);
-				goto retry;
-			}
+	if (inode->i_state & I_NEW) {
+		XFS_STATS_INC(vn_active);
+		XFS_STATS_INC(vn_alloc);
 
-			if (lock_flags != 0)
-				xfs_ilock(ip, lock_flags);
-			XFS_STATS_INC(xs_ig_found);
-			*ipp = ip;
-			error = 0;
+		error = xfs_iget_core(inode, mp, tp, ino, flags,
+				lock_flags, ipp, bno);
+		if (error) {
+			make_bad_inode(inode);
+			if (inode->i_state & I_NEW)
+				unlock_new_inode(inode);
+			iput(inode);
 		}
-	} else
-		error = ENOMEM;	/* If we got no inode we are out of memory */
+		return error;
+	}
 
-	return error;
-}
+	/*
+	 * If the inode is not fully constructed due to
+	 * filehandle mismatches wait for the inode to go
+	 * away and try again.
+	 *
+	 * iget_locked will call __wait_on_freeing_inode
+	 * to wait for the inode to go away.
+	 */
+	if (is_bad_inode(inode)) {
+		iput(inode);
+		delay(1);
+		goto retry;
+	}
 
-/*
- * Do the setup for the various locks within the incore inode.
- */
-void
-xfs_inode_lock_init(
-	xfs_inode_t	*ip,
-	bhv_vnode_t	*vp)
-{
-	mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
-		     "xfsino", ip->i_ino);
-	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
-	init_waitqueue_head(&ip->i_ipin_wait);
-	atomic_set(&ip->i_pincount, 0);
-	initnsema(&ip->i_flock, 1, "xfsfino");
+	ip = XFS_I(inode);
+	if (!ip) {
+		iput(inode);
+		delay(1);
+		goto retry;
+	}
+
+	if (lock_flags != 0)
+		xfs_ilock(ip, lock_flags);
+	XFS_STATS_INC(xs_ig_found);
+	*ipp = ip;
+	return 0;
 }
 
 /*
@@ -465,11 +432,9 @@
 xfs_iput(xfs_inode_t	*ip,
 	 uint		lock_flags)
 {
-	bhv_vnode_t	*vp = XFS_ITOV(ip);
-
-	vn_trace_entry(ip, "xfs_iput", (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 	xfs_iunlock(ip, lock_flags);
-	VN_RELE(vp);
+	IRELE(ip);
 }
 
 /*
@@ -479,20 +444,19 @@
 xfs_iput_new(xfs_inode_t	*ip,
 	     uint		lock_flags)
 {
-	bhv_vnode_t	*vp = XFS_ITOV(ip);
-	struct inode	*inode = vn_to_inode(vp);
+	struct inode	*inode = ip->i_vnode;
 
-	vn_trace_entry(ip, "xfs_iput_new", (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	if ((ip->i_d.di_mode == 0)) {
 		ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
-		vn_mark_bad(vp);
+		make_bad_inode(inode);
 	}
 	if (inode->i_state & I_NEW)
 		unlock_new_inode(inode);
 	if (lock_flags)
 		xfs_iunlock(ip, lock_flags);
-	VN_RELE(vp);
+	IRELE(ip);
 }
 
 
@@ -505,8 +469,6 @@
 void
 xfs_ireclaim(xfs_inode_t *ip)
 {
-	bhv_vnode_t	*vp;
-
 	/*
 	 * Remove from old hash list and mount list.
 	 */
@@ -535,9 +497,8 @@
 	/*
 	 * Pull our behavior descriptor from the vnode chain.
 	 */
-	vp = XFS_ITOV_NULL(ip);
-	if (vp) {
-		vn_to_inode(vp)->i_private = NULL;
+	if (ip->i_vnode) {
+		ip->i_vnode->i_private = NULL;
 		ip->i_vnode = NULL;
 	}
 
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 3449480..a550546a 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -15,6 +15,8 @@
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/log2.h>
+
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_types.h"
@@ -826,15 +828,17 @@
 	xfs_icdinode_t		*dic = &ip->i_d;
 
 	return _xfs_dic2xflags(dic->di_flags) |
-				(XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
+				(XFS_IFORK_Q(ip) ? XFS_XFLAG_HASATTR : 0);
 }
 
 uint
 xfs_dic2xflags(
-	xfs_dinode_core_t	*dic)
+	xfs_dinode_t		*dip)
 {
+	xfs_dinode_core_t	*dic = &dip->di_core;
+
 	return _xfs_dic2xflags(be16_to_cpu(dic->di_flags)) |
-				(XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
+				(XFS_DFORK_Q(dip) ? XFS_XFLAG_HASATTR : 0);
 }
 
 /*
@@ -884,8 +888,8 @@
 	 * Initialize inode's trace buffers.
 	 * Do this before xfs_iformat in case it adds entries.
 	 */
-#ifdef	XFS_VNODE_TRACE
-	ip->i_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
+#ifdef	XFS_INODE_TRACE
+	ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_SLEEP);
 #endif
 #ifdef XFS_BMAP_TRACE
 	ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
@@ -1220,10 +1224,8 @@
 					ip->i_d.di_extsize = pip->i_d.di_extsize;
 				}
 			} else if ((mode & S_IFMT) == S_IFREG) {
-				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
 					di_flags |= XFS_DIFLAG_REALTIME;
-					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
-				}
 				if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
 					di_flags |= XFS_DIFLAG_EXTSIZE;
 					ip->i_d.di_extsize = pip->i_d.di_extsize;
@@ -1298,7 +1300,10 @@
 	if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
 		return;
 
-	if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE))
+	if (XFS_IS_REALTIME_INODE(ip))
+		return;
+
+	if (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
 		return;
 
 	nimaps = 2;
@@ -1711,7 +1716,7 @@
 		 * runs.
 		 */
 		XFS_BMAP_INIT(&free_list, &first_block);
-		error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore,
+		error = xfs_bunmapi(ntp, ip,
 				    first_unmap_block, unmap_len,
 				    XFS_BMAPI_AFLAG(fork) |
 				      (sync ? 0 : XFS_BMAPI_ASYNC),
@@ -1844,8 +1849,6 @@
 	xfs_fsize_t	new_size,
 	cred_t		*credp)
 {
-	int		error;
-
 	ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
 	ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
 	ASSERT(new_size > ip->i_size);
@@ -1855,9 +1858,7 @@
 	 * xfs_write_file() beyond the end of the file
 	 * and any blocks between the old and new file sizes.
 	 */
-	error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
-			     ip->i_size);
-	return error;
+	return xfs_zero_eof(ip, new_size, ip->i_size);
 }
 
 /*
@@ -1959,24 +1960,6 @@
 	ASSERT(agi->agi_unlinked[bucket_index]);
 	ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino);
 
-	error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
-	if (error)
-		return error;
-
-	/*
-	 * Clear the on-disk di_nlink. This is to prevent xfs_bulkstat
-	 * from picking up this inode when it is reclaimed (its incore state
-	 * initialzed but not flushed to disk yet). The in-core di_nlink is
-	 * already cleared in xfs_droplink() and a corresponding transaction
-	 * logged. The hack here just synchronizes the in-core to on-disk
-	 * di_nlink value in advance before the actual inode sync to disk.
-	 * This is OK because the inode is already unlinked and would never
-	 * change its di_nlink again for this inode generation.
-	 * This is a temporary hack that would require a proper fix
-	 * in the future.
-	 */
-	dip->di_core.di_nlink = 0;
-
 	if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) {
 		/*
 		 * There is already another inode in the bucket we need
@@ -1984,6 +1967,10 @@
 		 * Here we put the head pointer into our next pointer,
 		 * and then we fall through to point the head at us.
 		 */
+		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
+		if (error)
+			return error;
+
 		ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO);
 		/* both on-disk, don't endian flip twice */
 		dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
@@ -2209,7 +2196,6 @@
 	xfs_inode_log_item_t	*iip;
 	xfs_log_item_t		*lip;
 	xfs_perag_t		*pag = xfs_get_perag(mp, inum);
-	SPLDECL(s);
 
 	if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
 		blks_per_cluster = 1;
@@ -2311,9 +2297,9 @@
 				iip = (xfs_inode_log_item_t *)lip;
 				ASSERT(iip->ili_logged == 1);
 				lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done;
-				AIL_LOCK(mp,s);
+				spin_lock(&mp->m_ail_lock);
 				iip->ili_flush_lsn = iip->ili_item.li_lsn;
-				AIL_UNLOCK(mp, s);
+				spin_unlock(&mp->m_ail_lock);
 				xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
 				pre_flushed++;
 			}
@@ -2334,9 +2320,9 @@
 			iip->ili_last_fields = iip->ili_format.ilf_fields;
 			iip->ili_format.ilf_fields = 0;
 			iip->ili_logged = 1;
-			AIL_LOCK(mp,s);
+			spin_lock(&mp->m_ail_lock);
 			iip->ili_flush_lsn = iip->ili_item.li_lsn;
-			AIL_UNLOCK(mp, s);
+			spin_unlock(&mp->m_ail_lock);
 
 			xfs_buf_attach_iodone(bp,
 				(void(*)(xfs_buf_t*,xfs_log_item_t*))
@@ -2374,6 +2360,8 @@
 	int			error;
 	int			delete;
 	xfs_ino_t		first_ino;
+	xfs_dinode_t    	*dip;
+	xfs_buf_t       	*ibp;
 
 	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
 	ASSERT(ip->i_transp == tp);
@@ -2409,8 +2397,27 @@
 	 * by reincarnations of this inode.
 	 */
 	ip->i_d.di_gen++;
+
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
+	error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0);
+	if (error)
+		return error;
+
+        /*
+	* Clear the on-disk di_mode. This is to prevent xfs_bulkstat
+	* from picking up this inode when it is reclaimed (its incore state
+	* initialzed but not flushed to disk yet). The in-core di_mode is
+	* already cleared  and a corresponding transaction logged.
+	* The hack here just synchronizes the in-core to on-disk
+	* di_mode value in advance before the actual inode sync to disk.
+	* This is OK because the inode is already unlinked and would never
+	* change its di_mode again for this inode generation.
+	* This is a temporary hack that would require a proper fix
+	* in the future.
+	*/
+	dip->di_core.di_mode = 0;
+
 	if (delete) {
 		xfs_ifree_cluster(ip, tp, first_ino);
 	}
@@ -2735,7 +2742,6 @@
 xfs_idestroy(
 	xfs_inode_t	*ip)
 {
-
 	switch (ip->i_d.di_mode & S_IFMT) {
 	case S_IFREG:
 	case S_IFDIR:
@@ -2749,7 +2755,7 @@
 	mrfree(&ip->i_iolock);
 	freesema(&ip->i_flock);
 
-#ifdef XFS_VNODE_TRACE
+#ifdef XFS_INODE_TRACE
 	ktrace_free(ip->i_trace);
 #endif
 #ifdef XFS_BMAP_TRACE
@@ -2775,16 +2781,15 @@
 		 */
 		xfs_mount_t	*mp = ip->i_mount;
 		xfs_log_item_t	*lip = &ip->i_itemp->ili_item;
-		int		s;
 
 		ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
 				       XFS_FORCED_SHUTDOWN(ip->i_mount));
 		if (lip->li_flags & XFS_LI_IN_AIL) {
-			AIL_LOCK(mp, s);
+			spin_lock(&mp->m_ail_lock);
 			if (lip->li_flags & XFS_LI_IN_AIL)
-				xfs_trans_delete_ail(mp, lip, s);
+				xfs_trans_delete_ail(mp, lip);
 			else
-				AIL_UNLOCK(mp, s);
+				spin_unlock(&mp->m_ail_lock);
 		}
 		xfs_inode_item_destroy(ip);
 	}
@@ -2816,40 +2821,8 @@
 {
 	ASSERT(atomic_read(&ip->i_pincount) > 0);
 
-	if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) {
-
-		/*
-		 * If the inode is currently being reclaimed, the link between
-		 * the bhv_vnode and the xfs_inode will be broken after the
-		 * XFS_IRECLAIM* flag is set. Hence, if these flags are not
-		 * set, then we can move forward and mark the linux inode dirty
-		 * knowing that it is still valid as it won't freed until after
-		 * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The
-		 * i_flags_lock is used to synchronise the setting of the
-		 * XFS_IRECLAIM* flags and the breaking of the link, and so we
-		 * can execute atomically w.r.t to reclaim by holding this lock
-		 * here.
-		 *
-		 * However, we still need to issue the unpin wakeup call as the
-		 * inode reclaim may be blocked waiting for the inode to become
-		 * unpinned.
-		 */
-
-		if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) {
-			bhv_vnode_t	*vp = XFS_ITOV_NULL(ip);
-			struct inode *inode = NULL;
-
-			BUG_ON(vp == NULL);
-			inode = vn_to_inode(vp);
-			BUG_ON(inode->i_state & I_CLEAR);
-
-			/* make sync come back and flush this inode */
-			if (!(inode->i_state & (I_NEW|I_FREEING)))
-				mark_inode_dirty_sync(inode);
-		}
-		spin_unlock(&ip->i_flags_lock);
+	if (atomic_dec_and_test(&ip->i_pincount))
 		wake_up(&ip->i_ipin_wait);
-	}
 }
 
 /*
@@ -3338,7 +3311,6 @@
 #ifdef XFS_TRANS_DEBUG
 	int			first;
 #endif
-	SPLDECL(s);
 
 	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
 	ASSERT(issemalocked(&(ip->i_flock)));
@@ -3533,9 +3505,9 @@
 		iip->ili_logged = 1;
 
 		ASSERT(sizeof(xfs_lsn_t) == 8);	/* don't lock if it shrinks */
-		AIL_LOCK(mp,s);
+		spin_lock(&mp->m_ail_lock);
 		iip->ili_flush_lsn = iip->ili_item.li_lsn;
-		AIL_UNLOCK(mp, s);
+		spin_unlock(&mp->m_ail_lock);
 
 		/*
 		 * Attach the function xfs_iflush_done to the inode's
@@ -3611,95 +3583,6 @@
 	XFS_MOUNT_IUNLOCK(mp);
 }
 
-/*
- * xfs_iaccess: check accessibility of inode for mode.
- */
-int
-xfs_iaccess(
-	xfs_inode_t	*ip,
-	mode_t		mode,
-	cred_t		*cr)
-{
-	int		error;
-	mode_t		orgmode = mode;
-	struct inode	*inode = vn_to_inode(XFS_ITOV(ip));
-
-	if (mode & S_IWUSR) {
-		umode_t		imode = inode->i_mode;
-
-		if (IS_RDONLY(inode) &&
-		    (S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
-			return XFS_ERROR(EROFS);
-
-		if (IS_IMMUTABLE(inode))
-			return XFS_ERROR(EACCES);
-	}
-
-	/*
-	 * If there's an Access Control List it's used instead of
-	 * the mode bits.
-	 */
-	if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
-		return error ? XFS_ERROR(error) : 0;
-
-	if (current_fsuid(cr) != ip->i_d.di_uid) {
-		mode >>= 3;
-		if (!in_group_p((gid_t)ip->i_d.di_gid))
-			mode >>= 3;
-	}
-
-	/*
-	 * If the DACs are ok we don't need any capability check.
-	 */
-	if ((ip->i_d.di_mode & mode) == mode)
-		return 0;
-	/*
-	 * Read/write DACs are always overridable.
-	 * Executable DACs are overridable if at least one exec bit is set.
-	 */
-	if (!(orgmode & S_IXUSR) ||
-	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
-		if (capable_cred(cr, CAP_DAC_OVERRIDE))
-			return 0;
-
-	if ((orgmode == S_IRUSR) ||
-	    (S_ISDIR(inode->i_mode) && (!(orgmode & S_IWUSR)))) {
-		if (capable_cred(cr, CAP_DAC_READ_SEARCH))
-			return 0;
-#ifdef	NOISE
-		cmn_err(CE_NOTE, "Ick: mode=%o, orgmode=%o", mode, orgmode);
-#endif	/* NOISE */
-		return XFS_ERROR(EACCES);
-	}
-	return XFS_ERROR(EACCES);
-}
-
-/*
- * xfs_iroundup: round up argument to next power of two
- */
-uint
-xfs_iroundup(
-	uint	v)
-{
-	int i;
-	uint m;
-
-	if ((v & (v - 1)) == 0)
-		return v;
-	ASSERT((v & 0x80000000) == 0);
-	if ((v & (v + 1)) == 0)
-		return v + 1;
-	for (i = 0, m = 1; i < 31; i++, m <<= 1) {
-		if (v & m)
-			continue;
-		v |= m;
-		if ((v & (v + 1)) == 0)
-			return v + 1;
-	}
-	ASSERT(0);
-	return( 0 );
-}
-
 #ifdef XFS_ILOCK_TRACE
 ktrace_t	*xfs_ilock_trace_buf;
 
@@ -4206,7 +4089,7 @@
 			return;
 		}
 		if (!is_power_of_2(new_size)){
-			rnew_size = xfs_iroundup(new_size);
+			rnew_size = roundup_pow_of_two(new_size);
 		}
 		if (rnew_size != ifp->if_real_bytes) {
 			ifp->if_u1.if_extents =
@@ -4229,7 +4112,7 @@
 	else {
 		new_size += ifp->if_bytes;
 		if (!is_power_of_2(new_size)) {
-			rnew_size = xfs_iroundup(new_size);
+			rnew_size = roundup_pow_of_two(new_size);
 		}
 		xfs_iext_inline_to_direct(ifp, rnew_size);
 	}
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index e5aff92..bfcd72c 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -132,45 +132,6 @@
 	__uint16_t	da_pad;		/* DMIG extra padding */
 } dm_attrs_t;
 
-typedef struct xfs_iocore {
-	void			*io_obj;	/* pointer to container
-						 * inode or dcxvn structure */
-	struct xfs_mount	*io_mount;	/* fs mount struct ptr */
-#ifdef DEBUG
-	mrlock_t		*io_lock;	/* inode IO lock */
-	mrlock_t		*io_iolock;	/* inode IO lock */
-#endif
-
-	/* I/O state */
-	xfs_fsize_t		io_new_size;	/* sz when write completes */
-
-	/* Miscellaneous state. */
-	unsigned int		io_flags;	/* IO related flags */
-
-	/* DMAPI state */
-	dm_attrs_t		io_dmattrs;
-
-} xfs_iocore_t;
-
-#define        io_dmevmask     io_dmattrs.da_dmevmask
-#define        io_dmstate      io_dmattrs.da_dmstate
-
-#define XFS_IO_INODE(io)	((xfs_inode_t *) ((io)->io_obj))
-#define XFS_IO_DCXVN(io)	((dcxvn_t *) ((io)->io_obj))
-
-/*
- * Flags in the flags field
- */
-
-#define XFS_IOCORE_RT		0x1
-
-/*
- * xfs_iocore prototypes
- */
-
-extern void xfs_iocore_inode_init(struct xfs_inode *);
-extern void xfs_iocore_inode_reinit(struct xfs_inode *);
-
 /*
  * This is the xfs inode cluster structure.  This structure is used by
  * xfs_iflush to find inodes that share a cluster and can be flushed to disk at
@@ -181,7 +142,7 @@
 	xfs_daddr_t		icl_blkno;	/* starting block number of
 						 * the cluster */
 	struct xfs_buf		*icl_buf;	/* the inode buffer */
-	lock_t			icl_lock;	/* inode list lock */
+	spinlock_t		icl_lock;	/* inode list lock */
 } xfs_icluster_t;
 
 /*
@@ -283,9 +244,6 @@
 	struct xfs_inode	**i_refcache;	/* ptr to entry in ref cache */
 	struct xfs_inode	*i_release;	/* inode to unref */
 #endif
-	/* I/O state */
-	xfs_iocore_t		i_iocore;	/* I/O core */
-
 	/* Miscellaneous state. */
 	unsigned short		i_flags;	/* see defined flags below */
 	unsigned char		i_update_core;	/* timestamps/size is dirty */
@@ -298,9 +256,10 @@
 	struct hlist_node	i_cnode;	/* cluster link node */
 
 	xfs_fsize_t		i_size;		/* in-memory size */
+	xfs_fsize_t		i_new_size;	/* size when write completes */
 	atomic_t		i_iocount;	/* outstanding I/O count */
 	/* Trace buffers per inode. */
-#ifdef XFS_VNODE_TRACE
+#ifdef XFS_INODE_TRACE
 	struct ktrace		*i_trace;	/* general inode trace */
 #endif
 #ifdef XFS_BMAP_TRACE
@@ -382,17 +341,42 @@
 /*
  * Fork handling.
  */
-#define	XFS_IFORK_PTR(ip,w)		\
-	((w) == XFS_DATA_FORK ? &(ip)->i_df : (ip)->i_afp)
-#define	XFS_IFORK_Q(ip)			XFS_CFORK_Q(&(ip)->i_d)
-#define	XFS_IFORK_DSIZE(ip)		XFS_CFORK_DSIZE(&ip->i_d, ip->i_mount)
-#define	XFS_IFORK_ASIZE(ip)		XFS_CFORK_ASIZE(&ip->i_d, ip->i_mount)
-#define	XFS_IFORK_SIZE(ip,w)		XFS_CFORK_SIZE(&ip->i_d, ip->i_mount, w)
-#define	XFS_IFORK_FORMAT(ip,w)		XFS_CFORK_FORMAT(&ip->i_d, w)
-#define	XFS_IFORK_FMT_SET(ip,w,n)	XFS_CFORK_FMT_SET(&ip->i_d, w, n)
-#define	XFS_IFORK_NEXTENTS(ip,w)	XFS_CFORK_NEXTENTS(&ip->i_d, w)
-#define	XFS_IFORK_NEXT_SET(ip,w,n)	XFS_CFORK_NEXT_SET(&ip->i_d, w, n)
 
+#define XFS_IFORK_Q(ip)			((ip)->i_d.di_forkoff != 0)
+#define XFS_IFORK_BOFF(ip)		((int)((ip)->i_d.di_forkoff << 3))
+
+#define XFS_IFORK_PTR(ip,w)		\
+	((w) == XFS_DATA_FORK ? \
+		&(ip)->i_df : \
+		(ip)->i_afp)
+#define XFS_IFORK_DSIZE(ip) \
+	(XFS_IFORK_Q(ip) ? \
+		XFS_IFORK_BOFF(ip) : \
+		XFS_LITINO((ip)->i_mount))
+#define XFS_IFORK_ASIZE(ip) \
+	(XFS_IFORK_Q(ip) ? \
+		XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : \
+		0)
+#define XFS_IFORK_SIZE(ip,w) \
+	((w) == XFS_DATA_FORK ? \
+		XFS_IFORK_DSIZE(ip) : \
+		XFS_IFORK_ASIZE(ip))
+#define XFS_IFORK_FORMAT(ip,w) \
+	((w) == XFS_DATA_FORK ? \
+		(ip)->i_d.di_format : \
+		(ip)->i_d.di_aformat)
+#define XFS_IFORK_FMT_SET(ip,w,n) \
+	((w) == XFS_DATA_FORK ? \
+		((ip)->i_d.di_format = (n)) : \
+		((ip)->i_d.di_aformat = (n)))
+#define XFS_IFORK_NEXTENTS(ip,w) \
+	((w) == XFS_DATA_FORK ? \
+		(ip)->i_d.di_nextents : \
+		(ip)->i_d.di_anextents)
+#define XFS_IFORK_NEXT_SET(ip,w,n) \
+	((w) == XFS_DATA_FORK ? \
+		((ip)->i_d.di_nextents = (n)) : \
+		((ip)->i_d.di_anextents = (n)))
 
 #ifdef __KERNEL__
 
@@ -509,7 +493,6 @@
 void		xfs_ihash_free(struct xfs_mount *);
 xfs_inode_t	*xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
 				  struct xfs_trans *);
-void            xfs_inode_lock_init(xfs_inode_t *, bhv_vnode_t *);
 int		xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
 			 uint, uint, xfs_inode_t **, xfs_daddr_t);
 void		xfs_iput(xfs_inode_t *, uint);
@@ -545,7 +528,7 @@
 				   struct xfs_icdinode *);
 
 uint		xfs_ip2xflags(struct xfs_inode *);
-uint		xfs_dic2xflags(struct xfs_dinode_core *);
+uint		xfs_dic2xflags(struct xfs_dinode *);
 int		xfs_ifree(struct xfs_trans *, xfs_inode_t *,
 			   struct xfs_bmap_free *);
 int		xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
@@ -567,13 +550,12 @@
 int		xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
 int		xfs_iflush(xfs_inode_t *, uint);
 void		xfs_iflush_all(struct xfs_mount *);
-int		xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
-uint		xfs_iroundup(uint);
 void		xfs_ichgtime(xfs_inode_t *, int);
 xfs_fsize_t	xfs_file_last_byte(xfs_inode_t *);
 void		xfs_lock_inodes(xfs_inode_t **, int, int, uint);
 
 void		xfs_synchronize_atime(xfs_inode_t *);
+void		xfs_mark_inode_dirty_sync(xfs_inode_t *);
 
 xfs_bmbt_rec_host_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
 void		xfs_iext_insert(xfs_ifork_t *, xfs_extnum_t, xfs_extnum_t,
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 565d470..034ca72 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -274,6 +274,11 @@
 	 */
 	xfs_synchronize_atime(ip);
 
+	/*
+	 * make sure the linux inode is dirty
+	 */
+	xfs_mark_inode_dirty_sync(ip);
+
 	vecp->i_addr = (xfs_caddr_t)&ip->i_d;
 	vecp->i_len  = sizeof(xfs_dinode_core_t);
 	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);
@@ -615,7 +620,7 @@
 			return XFS_ITEM_PUSHBUF;
 		} else {
 			/*
-			 * We hold the AIL_LOCK, so we must specify the
+			 * We hold the AIL lock, so we must specify the
 			 * NONOTIFY flag so that we won't double trip.
 			 */
 			xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY);
@@ -749,7 +754,7 @@
  * marked delayed write. If that's the case, we'll initiate a bawrite on that
  * buffer to expedite the process.
  *
- * We aren't holding the AIL_LOCK (or the flush lock) when this gets called,
+ * We aren't holding the AIL lock (or the flush lock) when this gets called,
  * so it is inherently race-y.
  */
 STATIC void
@@ -792,7 +797,7 @@
 		if (XFS_BUF_ISDELAYWRITE(bp)) {
 			/*
 			 * We were racing with iflush because we don't hold
-			 * the AIL_LOCK or the flush lock. However, at this point,
+			 * the AIL lock or the flush lock. However, at this point,
 			 * we have the buffer, and we know that it's dirty.
 			 * So, it's possible that iflush raced with us, and
 			 * this item is already taken off the AIL.
@@ -968,7 +973,6 @@
 	xfs_inode_log_item_t	*iip)
 {
 	xfs_inode_t	*ip;
-	SPLDECL(s);
 
 	ip = iip->ili_inode;
 
@@ -983,15 +987,15 @@
 	 */
 	if (iip->ili_logged &&
 	    (iip->ili_item.li_lsn == iip->ili_flush_lsn)) {
-		AIL_LOCK(ip->i_mount, s);
+		spin_lock(&ip->i_mount->m_ail_lock);
 		if (iip->ili_item.li_lsn == iip->ili_flush_lsn) {
 			/*
 			 * xfs_trans_delete_ail() drops the AIL lock.
 			 */
 			xfs_trans_delete_ail(ip->i_mount,
-					     (xfs_log_item_t*)iip, s);
+					     (xfs_log_item_t*)iip);
 		} else {
-			AIL_UNLOCK(ip->i_mount, s);
+			spin_unlock(&ip->i_mount->m_ail_lock);
 		}
 	}
 
@@ -1025,21 +1029,19 @@
 {
 	xfs_inode_log_item_t	*iip;
 	xfs_mount_t		*mp;
-	SPLDECL(s);
 
 	iip = ip->i_itemp;
 	mp = ip->i_mount;
 	if (iip) {
 		if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {
-			AIL_LOCK(mp, s);
+			spin_lock(&mp->m_ail_lock);
 			if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {
 				/*
 				 * xfs_trans_delete_ail() drops the AIL lock.
 				 */
-				xfs_trans_delete_ail(mp, (xfs_log_item_t *)iip,
-					s);
+				xfs_trans_delete_ail(mp, (xfs_log_item_t *)iip);
 			} else
-				AIL_UNLOCK(mp, s);
+				spin_unlock(&mp->m_ail_lock);
 		}
 		iip->ili_logged = 0;
 		/*
diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c
deleted file mode 100644
index b27b5d5..0000000
--- a/fs/xfs/xfs_iocore.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_bit.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir2.h"
-#include "xfs_dfrag.h"
-#include "xfs_dmapi.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_inode_item.h"
-#include "xfs_itable.h"
-#include "xfs_btree.h"
-#include "xfs_alloc.h"
-#include "xfs_ialloc.h"
-#include "xfs_bmap.h"
-#include "xfs_error.h"
-#include "xfs_rw.h"
-#include "xfs_quota.h"
-#include "xfs_trans_space.h"
-#include "xfs_iomap.h"
-
-
-STATIC xfs_fsize_t
-xfs_size_fn(
-	xfs_inode_t		*ip)
-{
-	return XFS_ISIZE(ip);
-}
-
-STATIC int
-xfs_ioinit(
-	struct xfs_mount	*mp,
-	struct xfs_mount_args	*mntargs,
-	int			flags)
-{
-	return xfs_mountfs(mp, flags);
-}
-
-xfs_ioops_t	xfs_iocore_xfs = {
-	.xfs_ioinit		= (xfs_ioinit_t) xfs_ioinit,
-	.xfs_bmapi_func		= (xfs_bmapi_t) xfs_bmapi,
-	.xfs_bunmapi_func	= (xfs_bunmapi_t) xfs_bunmapi,
-	.xfs_bmap_eof_func	= (xfs_bmap_eof_t) xfs_bmap_eof,
-	.xfs_iomap_write_direct =
-			(xfs_iomap_write_direct_t) xfs_iomap_write_direct,
-	.xfs_iomap_write_delay =
-			(xfs_iomap_write_delay_t) xfs_iomap_write_delay,
-	.xfs_iomap_write_allocate =
-			(xfs_iomap_write_allocate_t) xfs_iomap_write_allocate,
-	.xfs_iomap_write_unwritten =
-			(xfs_iomap_write_unwritten_t) xfs_iomap_write_unwritten,
-	.xfs_ilock		= (xfs_lock_t) xfs_ilock,
-	.xfs_lck_map_shared	= (xfs_lck_map_shared_t) xfs_ilock_map_shared,
-	.xfs_ilock_demote	= (xfs_lock_demote_t) xfs_ilock_demote,
-	.xfs_ilock_nowait	= (xfs_lock_nowait_t) xfs_ilock_nowait,
-	.xfs_unlock		= (xfs_unlk_t) xfs_iunlock,
-	.xfs_size_func		= (xfs_size_t) xfs_size_fn,
-	.xfs_iodone		= (xfs_iodone_t) fs_noerr,
-	.xfs_swap_extents_func	= (xfs_swap_extents_t) xfs_swap_extents,
-};
-
-void
-xfs_iocore_inode_reinit(
-	xfs_inode_t	*ip)
-{
-	xfs_iocore_t	*io = &ip->i_iocore;
-
-	io->io_flags = 0;
-	if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
-		io->io_flags |= XFS_IOCORE_RT;
-	io->io_dmevmask = ip->i_d.di_dmevmask;
-	io->io_dmstate = ip->i_d.di_dmstate;
-}
-
-void
-xfs_iocore_inode_init(
-	xfs_inode_t	*ip)
-{
-	xfs_iocore_t	*io = &ip->i_iocore;
-	xfs_mount_t	*mp = ip->i_mount;
-
-	io->io_mount = mp;
-#ifdef DEBUG
-	io->io_lock = &ip->i_lock;
-	io->io_iolock = &ip->i_iolock;
-#endif
-
-	io->io_obj = (void *)ip;
-
-	xfs_iocore_inode_reinit(ip);
-}
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 72786e3..fde37f8 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -53,12 +53,10 @@
 void
 xfs_iomap_enter_trace(
 	int		tag,
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_off_t	offset,
 	ssize_t		count)
 {
-	xfs_inode_t	*ip = XFS_IO_INODE(io);
-
 	if (!ip->i_rwtrace)
 		return;
 
@@ -70,8 +68,8 @@
 		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(offset & 0xffffffff)),
 		(void *)((unsigned long)count),
-		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
-		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
+		(void *)((unsigned long)((ip->i_new_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_new_size & 0xffffffff)),
 		(void *)((unsigned long)current_pid()),
 		(void *)NULL,
 		(void *)NULL,
@@ -84,15 +82,13 @@
 void
 xfs_iomap_map_trace(
 	int		tag,
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_off_t	offset,
 	ssize_t		count,
 	xfs_iomap_t	*iomapp,
 	xfs_bmbt_irec_t	*imapp,
 	int		flags)
 {
-	xfs_inode_t	*ip = XFS_IO_INODE(io);
-
 	if (!ip->i_rwtrace)
 		return;
 
@@ -126,7 +122,7 @@
 
 STATIC int
 xfs_imap_to_bmap(
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_off_t	offset,
 	xfs_bmbt_irec_t *imap,
 	xfs_iomap_t	*iomapp,
@@ -134,11 +130,10 @@
 	int		iomaps,			/* Number of iomap entries */
 	int		flags)
 {
-	xfs_mount_t	*mp;
+	xfs_mount_t	*mp = ip->i_mount;
 	int		pbm;
 	xfs_fsblock_t	start_block;
 
-	mp = io->io_mount;
 
 	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
 		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
@@ -146,7 +141,7 @@
 		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
 		iomapp->iomap_flags = flags;
 
-		if (io->io_flags & XFS_IOCORE_RT) {
+		if (XFS_IS_REALTIME_INODE(ip)) {
 			iomapp->iomap_flags |= IOMAP_REALTIME;
 			iomapp->iomap_target = mp->m_rtdev_targp;
 		} else {
@@ -160,7 +155,7 @@
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
 			iomapp->iomap_flags |= IOMAP_DELAY;
 		} else {
-			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
+			iomapp->iomap_bn = XFS_FSB_TO_DB(ip, start_block);
 			if (ISUNWRITTEN(imap))
 				iomapp->iomap_flags |= IOMAP_UNWRITTEN;
 		}
@@ -172,14 +167,14 @@
 
 int
 xfs_iomap(
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_off_t	offset,
 	ssize_t		count,
 	int		flags,
 	xfs_iomap_t	*iomapp,
 	int		*niomaps)
 {
-	xfs_mount_t	*mp = io->io_mount;
+	xfs_mount_t	*mp = ip->i_mount;
 	xfs_fileoff_t	offset_fsb, end_fsb;
 	int		error = 0;
 	int		lockmode = 0;
@@ -188,45 +183,37 @@
 	int		bmapi_flags = 0;
 	int		iomap_flags = 0;
 
+	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
+
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
-	switch (flags &
-		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
-		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
+	switch (flags & (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE)) {
 	case BMAPI_READ:
-		xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
-		lockmode = XFS_LCK_MAP_SHARED(mp, io);
+		xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, ip, offset, count);
+		lockmode = xfs_ilock_map_shared(ip);
 		bmapi_flags = XFS_BMAPI_ENTIRE;
 		break;
 	case BMAPI_WRITE:
-		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
+		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, ip, offset, count);
 		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
 		if (flags & BMAPI_IGNSTATE)
 			bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;
-		XFS_ILOCK(mp, io, lockmode);
+		xfs_ilock(ip, lockmode);
 		break;
 	case BMAPI_ALLOCATE:
-		xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);
+		xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, ip, offset, count);
 		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
 		bmapi_flags = XFS_BMAPI_ENTIRE;
+
 		/* Attempt non-blocking lock */
 		if (flags & BMAPI_TRYLOCK) {
-			if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
+			if (!xfs_ilock_nowait(ip, lockmode))
 				return XFS_ERROR(EAGAIN);
 		} else {
-			XFS_ILOCK(mp, io, lockmode);
+			xfs_ilock(ip, lockmode);
 		}
 		break;
-	case BMAPI_UNWRITTEN:
-		goto phase2;
-	case BMAPI_DEVICE:
-		lockmode = XFS_LCK_MAP_SHARED(mp, io);
-		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
-			mp->m_rtdev_targp : mp->m_ddev_targp;
-		error = 0;
-		*niomaps = 1;
-		goto out;
 	default:
 		BUG();
 	}
@@ -237,7 +224,7 @@
 	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 
-	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
+	error = xfs_bmapi(NULL, ip, offset_fsb,
 			(xfs_filblks_t)(end_fsb - offset_fsb),
 			bmapi_flags,  NULL, 0, &imap,
 			&nimaps, NULL, NULL);
@@ -245,54 +232,48 @@
 	if (error)
 		goto out;
 
-phase2:
-	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
+	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)) {
 	case BMAPI_WRITE:
 		/* If we found an extent, return it */
 		if (nimaps &&
 		    (imap.br_startblock != HOLESTARTBLOCK) &&
 		    (imap.br_startblock != DELAYSTARTBLOCK)) {
-			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
+			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, ip,
 					offset, count, iomapp, &imap, flags);
 			break;
 		}
 
 		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
-			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
-					count, flags, &imap, &nimaps, nimaps);
+			error = xfs_iomap_write_direct(ip, offset, count, flags,
+						       &imap, &nimaps, nimaps);
 		} else {
-			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
-					flags, &imap, &nimaps);
+			error = xfs_iomap_write_delay(ip, offset, count, flags,
+						      &imap, &nimaps);
 		}
 		if (!error) {
-			xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,
+			xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, ip,
 					offset, count, iomapp, &imap, flags);
 		}
 		iomap_flags = IOMAP_NEW;
 		break;
 	case BMAPI_ALLOCATE:
 		/* If we found an extent, return it */
-		XFS_IUNLOCK(mp, io, lockmode);
+		xfs_iunlock(ip, lockmode);
 		lockmode = 0;
 
 		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) {
-			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
+			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, ip,
 					offset, count, iomapp, &imap, flags);
 			break;
 		}
 
-		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count,
+		error = xfs_iomap_write_allocate(ip, offset, count,
 						 &imap, &nimaps);
 		break;
-	case BMAPI_UNWRITTEN:
-		lockmode = 0;
-		error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);
-		nimaps = 0;
-		break;
 	}
 
 	if (nimaps) {
-		*niomaps = xfs_imap_to_bmap(io, offset, &imap,
+		*niomaps = xfs_imap_to_bmap(ip, offset, &imap,
 					    iomapp, nimaps, *niomaps, iomap_flags);
 	} else if (niomaps) {
 		*niomaps = 0;
@@ -300,14 +281,15 @@
 
 out:
 	if (lockmode)
-		XFS_IUNLOCK(mp, io, lockmode);
+		xfs_iunlock(ip, lockmode);
 	return XFS_ERROR(error);
 }
 
+
 STATIC int
 xfs_iomap_eof_align_last_fsb(
 	xfs_mount_t	*mp,
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_fsize_t	isize,
 	xfs_extlen_t	extsize,
 	xfs_fileoff_t	*last_fsb)
@@ -316,7 +298,7 @@
 	xfs_extlen_t	align;
 	int		eof, error;
 
-	if (io->io_flags & XFS_IOCORE_RT)
+	if (XFS_IS_REALTIME_INODE(ip))
 		;
 	/*
 	 * If mounted with the "-o swalloc" option, roundup the allocation
@@ -347,7 +329,7 @@
 	}
 
 	if (new_last_fsb) {
-		error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
+		error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
 		if (error)
 			return error;
 		if (eof)
@@ -416,7 +398,6 @@
 	int		found)
 {
 	xfs_mount_t	*mp = ip->i_mount;
-	xfs_iocore_t	*io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb;
 	xfs_fileoff_t	last_fsb;
 	xfs_filblks_t	count_fsb, resaligned;
@@ -446,13 +427,13 @@
 	extsz = xfs_get_extsz_hint(ip);
 
 	isize = ip->i_size;
-	if (io->io_new_size > isize)
-		isize = io->io_new_size;
+	if (ip->i_new_size > isize)
+		isize = ip->i_new_size;
 
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
 	if ((offset + count) > isize) {
-		error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
+		error = xfs_iomap_eof_align_last_fsb(mp, ip, isize, extsz,
 							&last_fsb);
 		if (error)
 			goto error_out;
@@ -519,7 +500,7 @@
 	 */
 	XFS_BMAP_INIT(&free_list, &firstfsb);
 	nimaps = 1;
-	error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag,
+	error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag,
 		&firstfsb, 0, &imap, &nimaps, &free_list, NULL);
 	if (error)
 		goto error0;
@@ -542,7 +523,8 @@
 		goto error_out;
 	}
 
-	if (unlikely(!imap.br_startblock && !(io->io_flags & XFS_IOCORE_RT))) {
+	if (unlikely(!imap.br_startblock &&
+		     !(XFS_IS_REALTIME_INODE(ip)))) {
 		error = xfs_cmn_err_fsblock_zero(ip, &imap);
 		goto error_out;
 	}
@@ -577,7 +559,7 @@
 STATIC int
 xfs_iomap_eof_want_preallocate(
 	xfs_mount_t	*mp,
-	xfs_iocore_t	*io,
+	xfs_inode_t	*ip,
 	xfs_fsize_t	isize,
 	xfs_off_t	offset,
 	size_t		count,
@@ -604,7 +586,7 @@
 	while (count_fsb > 0) {
 		imaps = nimaps;
 		firstblock = NULLFSBLOCK;
-		error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0,
+		error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0,
 				  &firstblock, 0, imap, &imaps, NULL, NULL);
 		if (error)
 			return error;
@@ -630,7 +612,6 @@
 	int		*nmaps)
 {
 	xfs_mount_t	*mp = ip->i_mount;
-	xfs_iocore_t	*io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb;
 	xfs_fileoff_t	last_fsb;
 	xfs_off_t	aligned_offset;
@@ -658,10 +639,10 @@
 
 retry:
 	isize = ip->i_size;
-	if (io->io_new_size > isize)
-		isize = io->io_new_size;
+	if (ip->i_new_size > isize)
+		isize = ip->i_new_size;
 
-	error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count,
+	error = xfs_iomap_eof_want_preallocate(mp, ip, isize, offset, count,
 				ioflag, imap, XFS_WRITE_IMAPS, &prealloc);
 	if (error)
 		return error;
@@ -675,7 +656,7 @@
 	}
 
 	if (prealloc || extsz) {
-		error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
+		error = xfs_iomap_eof_align_last_fsb(mp, ip, isize, extsz,
 							&last_fsb);
 		if (error)
 			return error;
@@ -683,7 +664,7 @@
 
 	nimaps = XFS_WRITE_IMAPS;
 	firstblock = NULLFSBLOCK;
-	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
+	error = xfs_bmapi(NULL, ip, offset_fsb,
 			  (xfs_filblks_t)(last_fsb - offset_fsb),
 			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
 			  XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
@@ -697,7 +678,7 @@
 	 */
 	if (nimaps == 0) {
 		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
-					io, offset, count);
+					ip, offset, count);
 		if (xfs_flush_space(ip, &fsynced, &ioflag))
 			return XFS_ERROR(ENOSPC);
 
@@ -705,7 +686,8 @@
 		goto retry;
 	}
 
-	if (unlikely(!imap[0].br_startblock && !(io->io_flags & XFS_IOCORE_RT)))
+	if (unlikely(!imap[0].br_startblock &&
+		     !(XFS_IS_REALTIME_INODE(ip))))
 		return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
 
 	*ret_imap = imap[0];
@@ -720,6 +702,9 @@
  * the originating callers request.
  *
  * Called without a lock on the inode.
+ *
+ * We no longer bother to look at the incoming map - all we have to
+ * guarantee is that whatever we allocate fills the required range.
  */
 int
 xfs_iomap_write_allocate(
@@ -730,15 +715,14 @@
 	int		*retmap)
 {
 	xfs_mount_t	*mp = ip->i_mount;
-	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb, last_block;
 	xfs_fileoff_t	end_fsb, map_start_fsb;
 	xfs_fsblock_t	first_block;
 	xfs_bmap_free_t	free_list;
 	xfs_filblks_t	count_fsb;
-	xfs_bmbt_irec_t	imap[XFS_STRAT_WRITE_IMAPS];
+	xfs_bmbt_irec_t	imap;
 	xfs_trans_t	*tp;
-	int		i, nimaps, committed;
+	int		nimaps, committed;
 	int		error = 0;
 	int		nres;
 
@@ -785,13 +769,38 @@
 
 			XFS_BMAP_INIT(&free_list, &first_block);
 
-			nimaps = XFS_STRAT_WRITE_IMAPS;
 			/*
-			 * Ensure we don't go beyond eof - it is possible
-			 * the extents changed since we did the read call,
-			 * we dropped the ilock in the interim.
+			 * it is possible that the extents have changed since
+			 * we did the read call as we dropped the ilock for a
+			 * while. We have to be careful about truncates or hole
+			 * punchs here - we are not allowed to allocate
+			 * non-delalloc blocks here.
+			 *
+			 * The only protection against truncation is the pages
+			 * for the range we are being asked to convert are
+			 * locked and hence a truncate will block on them
+			 * first.
+			 *
+			 * As a result, if we go beyond the range we really
+			 * need and hit an delalloc extent boundary followed by
+			 * a hole while we have excess blocks in the map, we
+			 * will fill the hole incorrectly and overrun the
+			 * transaction reservation.
+			 *
+			 * Using a single map prevents this as we are forced to
+			 * check each map we look for overlap with the desired
+			 * range and abort as soon as we find it. Also, given
+			 * that we only return a single map, having one beyond
+			 * what we can return is probably a bit silly.
+			 *
+			 * We also need to check that we don't go beyond EOF;
+			 * this is a truncate optimisation as a truncate sets
+			 * the new file size before block on the pages we
+			 * currently have locked under writeback. Because they
+			 * are about to be tossed, we don't need to write them
+			 * back....
 			 */
-
+			nimaps = 1;
 			end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
 			xfs_bmap_last_offset(NULL, ip, &last_block,
 				XFS_DATA_FORK);
@@ -805,9 +814,9 @@
 			}
 
 			/* Go get the actual blocks */
-			error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb,
+			error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
 					XFS_BMAPI_WRITE, &first_block, 1,
-					imap, &nimaps, &free_list, NULL);
+					&imap, &nimaps, &free_list, NULL);
 			if (error)
 				goto trans_cancel;
 
@@ -826,27 +835,24 @@
 		 * See if we were able to allocate an extent that
 		 * covers at least part of the callers request
 		 */
-		for (i = 0; i < nimaps; i++) {
-			if (unlikely(!imap[i].br_startblock &&
-				     !(io->io_flags & XFS_IOCORE_RT)))
-				return xfs_cmn_err_fsblock_zero(ip, &imap[i]);
-			if ((offset_fsb >= imap[i].br_startoff) &&
-			    (offset_fsb < (imap[i].br_startoff +
-					   imap[i].br_blockcount))) {
-				*map = imap[i];
-				*retmap = 1;
-				XFS_STATS_INC(xs_xstrat_quick);
-				return 0;
-			}
-			count_fsb -= imap[i].br_blockcount;
+		if (unlikely(!imap.br_startblock &&
+			     XFS_IS_REALTIME_INODE(ip)))
+			return xfs_cmn_err_fsblock_zero(ip, &imap);
+		if ((offset_fsb >= imap.br_startoff) &&
+		    (offset_fsb < (imap.br_startoff +
+				   imap.br_blockcount))) {
+			*map = imap;
+			*retmap = 1;
+			XFS_STATS_INC(xs_xstrat_quick);
+			return 0;
 		}
 
-		/* So far we have not mapped the requested part of the
+		/*
+		 * So far we have not mapped the requested part of the
 		 * file, just surrounding data, try again.
 		 */
-		nimaps--;
-		map_start_fsb = imap[nimaps].br_startoff +
-				imap[nimaps].br_blockcount;
+		count_fsb -= imap.br_blockcount;
+		map_start_fsb = imap.br_startoff + imap.br_blockcount;
 	}
 
 trans_cancel:
@@ -864,7 +870,6 @@
 	size_t		count)
 {
 	xfs_mount_t	*mp = ip->i_mount;
-	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb;
 	xfs_filblks_t	count_fsb;
 	xfs_filblks_t	numblks_fsb;
@@ -877,8 +882,7 @@
 	int		committed;
 	int		error;
 
-	xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN,
-				&ip->i_iocore, offset, count);
+	xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, ip, offset, count);
 
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
@@ -912,7 +916,7 @@
 		 */
 		XFS_BMAP_INIT(&free_list, &firstfsb);
 		nimaps = 1;
-		error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb,
+		error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
 				  XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb,
 				  1, &imap, &nimaps, &free_list, NULL);
 		if (error)
@@ -928,7 +932,7 @@
 			return XFS_ERROR(error);
 
 		if (unlikely(!imap.br_startblock &&
-			     !(io->io_flags & XFS_IOCORE_RT)))
+			     !(XFS_IS_REALTIME_INODE(ip))))
 			return xfs_cmn_err_fsblock_zero(ip, &imap);
 
 		if ((numblks_fsb = imap.br_blockcount) == 0) {
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index f5c0988..ee1a0c1 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -36,14 +36,12 @@
 	BMAPI_READ = (1 << 0),		/* read extents */
 	BMAPI_WRITE = (1 << 1),		/* create extents */
 	BMAPI_ALLOCATE = (1 << 2),	/* delayed allocate to real extents */
-	BMAPI_UNWRITTEN  = (1 << 3),	/* unwritten extents to real extents */
 	/* modifiers */
 	BMAPI_IGNSTATE = (1 << 4),	/* ignore unwritten state on read */
 	BMAPI_DIRECT = (1 << 5),	/* direct instead of buffered write */
 	BMAPI_MMAP = (1 << 6),		/* allocate for mmap write */
 	BMAPI_SYNC = (1 << 7),		/* sync write to flush delalloc space */
 	BMAPI_TRYLOCK = (1 << 8),	/* non-blocking request */
-	BMAPI_DEVICE = (1 << 9),	/* we only want to know the device */
 } bmapi_flags_t;
 
 
@@ -73,11 +71,10 @@
 	iomap_flags_t		iomap_flags;
 } xfs_iomap_t;
 
-struct xfs_iocore;
 struct xfs_inode;
 struct xfs_bmbt_irec;
 
-extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
+extern int xfs_iomap(struct xfs_inode *, xfs_off_t, ssize_t, int,
 		     struct xfs_iomap *, int *);
 extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
 				  int, struct xfs_bmbt_irec *, int *, int);
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 9fc4c28..658aab6 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -170,7 +170,7 @@
 	buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
 	buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
 	buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
-	buf->bs_xflags = xfs_dic2xflags(dic);
+	buf->bs_xflags = xfs_dic2xflags(dip);
 	buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
 	buf->bs_extents = be32_to_cpu(dic->di_nextents);
 	buf->bs_gen = be32_to_cpu(dic->di_gen);
@@ -291,7 +291,7 @@
 	dip = (xfs_dinode_t *)
 			xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
 	/*
-	 * Check the buffer containing the on-disk inode for di_nlink == 0.
+	 * Check the buffer containing the on-disk inode for di_mode == 0.
 	 * This is to prevent xfs_bulkstat from picking up just reclaimed
 	 * inodes that have their in-core state initialized but not flushed
 	 * to disk yet. This is a temporary hack that would require a proper
@@ -299,7 +299,7 @@
 	 */
 	if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC ||
 	    !XFS_DINODE_GOOD_VERSION(dip->di_core.di_version) ||
-	    !dip->di_core.di_nlink)
+	    !dip->di_core.di_mode)
 		return 0;
 	if (flags & BULKSTAT_FG_QUICK) {
 		*dipp = dip;
@@ -307,7 +307,7 @@
 	}
 	/* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
 	aformat = dip->di_core.di_aformat;
-	if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
+	if ((XFS_DFORK_Q(dip) == 0) ||
 	    (aformat == XFS_DINODE_FMT_LOCAL) ||
 	    (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
 		*dipp = dip;
@@ -399,7 +399,7 @@
 		(XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
 	nimask = ~(nicluster - 1);
 	nbcluster = nicluster >> mp->m_sb.sb_inopblog;
-	irbuf = kmem_zalloc_greedy(&irbsize, NBPC, NBPC * 4,
+	irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4,
 				   KM_SLEEP | KM_MAYFAIL | KM_LARGE);
 	nirbuf = irbsize / sizeof(*irbuf);
 
@@ -830,7 +830,7 @@
 	agino = XFS_INO_TO_AGINO(mp, ino);
 	left = *count;
 	*count = 0;
-	bcount = MIN(left, (int)(NBPP / sizeof(*buffer)));
+	bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
 	buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
 	error = bufidx = 0;
 	cur = NULL;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 77c1271..b3ac380 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -399,10 +399,10 @@
 {
 	xlog_t *log = mp->m_log;
 	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
-	int	abortflg, spl;
+	int	abortflg;
 
 	cb->cb_next = NULL;
-	spl = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
 	if (!abortflg) {
 		ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
@@ -411,7 +411,7 @@
 		*(iclog->ic_callback_tail) = cb;
 		iclog->ic_callback_tail = &(cb->cb_next);
 	}
-	LOG_UNLOCK(log, spl);
+	spin_unlock(&log->l_icloglock);
 	return abortflg;
 }	/* xfs_log_notify */
 
@@ -498,11 +498,14 @@
  * Return error or zero.
  */
 int
-xfs_log_mount(xfs_mount_t	*mp,
-	      xfs_buftarg_t	*log_target,
-	      xfs_daddr_t	blk_offset,
-	      int		num_bblks)
+xfs_log_mount(
+	xfs_mount_t	*mp,
+	xfs_buftarg_t	*log_target,
+	xfs_daddr_t	blk_offset,
+	int		num_bblks)
 {
+	int		error;
+
 	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
 		cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);
 	else {
@@ -515,11 +518,21 @@
 	mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
 
 	/*
+	 * Initialize the AIL now we have a log.
+	 */
+	spin_lock_init(&mp->m_ail_lock);
+	error = xfs_trans_ail_init(mp);
+	if (error) {
+		cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error);
+		goto error;
+	}
+
+	/*
 	 * skip log recovery on a norecovery mount.  pretend it all
 	 * just worked.
 	 */
 	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
-		int		error, readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
+		int	readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
 
 		if (readonly)
 			mp->m_flags &= ~XFS_MOUNT_RDONLY;
@@ -530,8 +543,7 @@
 			mp->m_flags |= XFS_MOUNT_RDONLY;
 		if (error) {
 			cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
-			xlog_dealloc_log(mp->m_log);
-			return error;
+			goto error;
 		}
 	}
 
@@ -540,6 +552,9 @@
 
 	/* End mounting message in xfs_log_mount_finish */
 	return 0;
+error:
+	xfs_log_unmount_dealloc(mp);
+	return error;
 }	/* xfs_log_mount */
 
 /*
@@ -606,7 +621,6 @@
 	xfs_log_ticket_t tic = NULL;
 	xfs_lsn_t	 lsn;
 	int		 error;
-	SPLDECL(s);
 
 	/* the data section must be 32 bit size aligned */
 	struct {
@@ -659,24 +673,24 @@
 		}
 
 
-		s = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 		iclog = log->l_iclog;
 		iclog->ic_refcnt++;
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		xlog_state_want_sync(log, iclog);
 		(void) xlog_state_release_iclog(log, iclog);
 
-		s = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 		if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
 		      iclog->ic_state == XLOG_STATE_DIRTY)) {
 			if (!XLOG_FORCED_SHUTDOWN(log)) {
 				sv_wait(&iclog->ic_forcesema, PMEM,
 					&log->l_icloglock, s);
 			} else {
-				LOG_UNLOCK(log, s);
+				spin_unlock(&log->l_icloglock);
 			}
 		} else {
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 		}
 		if (tic) {
 			xlog_trace_loggrant(log, tic, "unmount rec");
@@ -697,15 +711,15 @@
 		 * a file system that went into forced_shutdown as
 		 * the result of an unmount..
 		 */
-		s = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 		iclog = log->l_iclog;
 		iclog->ic_refcnt++;
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 
 		xlog_state_want_sync(log, iclog);
 		(void) xlog_state_release_iclog(log, iclog);
 
-		s = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 
 		if ( ! (   iclog->ic_state == XLOG_STATE_ACTIVE
 			|| iclog->ic_state == XLOG_STATE_DIRTY
@@ -714,7 +728,7 @@
 				sv_wait(&iclog->ic_forcesema, PMEM,
 					&log->l_icloglock, s);
 		} else {
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 		}
 	}
 
@@ -723,10 +737,14 @@
 
 /*
  * Deallocate log structures for unmount/relocation.
+ *
+ * We need to stop the aild from running before we destroy
+ * and deallocate the log as the aild references the log.
  */
 void
 xfs_log_unmount_dealloc(xfs_mount_t *mp)
 {
+	xfs_trans_ail_destroy(mp);
 	xlog_dealloc_log(mp->m_log);
 }
 
@@ -762,20 +780,18 @@
 	xlog_ticket_t	*tic;
 	xlog_t		*log = mp->m_log;
 	int		need_bytes, free_bytes, cycle, bytes;
-	SPLDECL(s);
 
 	if (XLOG_FORCED_SHUTDOWN(log))
 		return;
-	ASSERT(!XFS_FORCED_SHUTDOWN(mp));
 
 	if (tail_lsn == 0) {
 		/* needed since sync_lsn is 64 bits */
-		s = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 		tail_lsn = log->l_last_sync_lsn;
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 	}
 
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 
 	/* Also an invalid lsn.  1 implies that we aren't passing in a valid
 	 * tail_lsn.
@@ -824,7 +840,7 @@
 			tic = tic->t_next;
 		} while (tic != log->l_reserve_headq);
 	}
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 }	/* xfs_log_move_tail */
 
 /*
@@ -836,14 +852,13 @@
 int
 xfs_log_need_covered(xfs_mount_t *mp)
 {
-	SPLDECL(s);
 	int		needed = 0, gen;
 	xlog_t		*log = mp->m_log;
 
 	if (!xfs_fs_writable(mp))
 		return 0;
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	if (((log->l_covered_state == XLOG_STATE_COVER_NEED) ||
 		(log->l_covered_state == XLOG_STATE_COVER_NEED2))
 			&& !xfs_trans_first_ail(mp, &gen)
@@ -856,7 +871,7 @@
 		}
 		needed = 1;
 	}
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 	return needed;
 }
 
@@ -881,17 +896,16 @@
 xlog_assign_tail_lsn(xfs_mount_t *mp)
 {
 	xfs_lsn_t tail_lsn;
-	SPLDECL(s);
 	xlog_t	  *log = mp->m_log;
 
 	tail_lsn = xfs_trans_tail_ail(mp);
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 	if (tail_lsn != 0) {
 		log->l_tail_lsn = tail_lsn;
 	} else {
 		tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn;
 	}
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 
 	return tail_lsn;
 }	/* xlog_assign_tail_lsn */
@@ -911,7 +925,7 @@
  * the tail.  The details of this case are described below, but the end
  * result is that we return the size of the log as the amount of space left.
  */
-int
+STATIC int
 xlog_space_left(xlog_t *log, int cycle, int bytes)
 {
 	int free_bytes;
@@ -1165,7 +1179,7 @@
 	log->l_flags	   |= XLOG_ACTIVE_RECOVERY;
 
 	log->l_prev_block  = -1;
-	ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, 1, 0);
+	log->l_tail_lsn	   = xlog_assign_lsn(1, 0);
 	/* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */
 	log->l_last_sync_lsn = log->l_tail_lsn;
 	log->l_curr_cycle  = 1;	    /* 0 is bad since this is initial value */
@@ -1193,8 +1207,8 @@
 	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 	log->l_xbuf = bp;
 
-	spinlock_init(&log->l_icloglock, "iclog");
-	spinlock_init(&log->l_grant_lock, "grhead_iclog");
+	spin_lock_init(&log->l_icloglock);
+	spin_lock_init(&log->l_grant_lock);
 	initnsema(&log->l_flushsema, 0, "ic-flush");
 	xlog_state_ticket_alloc(log);  /* wait until after icloglock inited */
 
@@ -1231,12 +1245,12 @@
 
 		head = &iclog->ic_header;
 		memset(head, 0, sizeof(xlog_rec_header_t));
-		INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
-		INT_SET(head->h_version, ARCH_CONVERT,
+		head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
+		head->h_version = cpu_to_be32(
 			XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? 2 : 1);
-		INT_SET(head->h_size, ARCH_CONVERT, log->l_iclog_size);
+		head->h_size = cpu_to_be32(log->l_iclog_size);
 		/* new fields */
-		INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
+		head->h_fmt = cpu_to_be32(XLOG_FMT);
 		memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
 
 
@@ -1293,7 +1307,7 @@
  * pushes on an lsn which is further along in the log once we reach the high
  * water mark.  In this manner, we would be creating a low water mark.
  */
-void
+STATIC void
 xlog_grant_push_ail(xfs_mount_t	*mp,
 		    int		need_bytes)
 {
@@ -1305,11 +1319,10 @@
     int		threshold_block;	/* block in lsn we'd like to be at */
     int		threshold_cycle;	/* lsn cycle we'd like to be at */
     int		free_threshold;
-    SPLDECL(s);
 
     ASSERT(BTOBB(need_bytes) < log->l_logBBsize);
 
-    s = GRANT_LOCK(log);
+    spin_lock(&log->l_grant_lock);
     free_bytes = xlog_space_left(log,
 				 log->l_grant_reserve_cycle,
 				 log->l_grant_reserve_bytes);
@@ -1331,8 +1344,7 @@
 	    threshold_block -= log->l_logBBsize;
 	    threshold_cycle += 1;
 	}
-	ASSIGN_ANY_LSN_HOST(threshold_lsn, threshold_cycle,
-		       threshold_block);
+	threshold_lsn = xlog_assign_lsn(threshold_cycle, threshold_block);
 
 	/* Don't pass in an lsn greater than the lsn of the last
 	 * log record known to be on disk.
@@ -1340,7 +1352,7 @@
 	if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0)
 	    threshold_lsn = log->l_last_sync_lsn;
     }
-    GRANT_UNLOCK(log, s);
+    spin_unlock(&log->l_grant_lock);
 
     /*
      * Get the transaction layer to kick the dirty buffers out to
@@ -1378,19 +1390,18 @@
  * is added immediately before calling bwrite().
  */
 
-int
+STATIC int
 xlog_sync(xlog_t		*log,
 	  xlog_in_core_t	*iclog)
 {
 	xfs_caddr_t	dptr;		/* pointer to byte sized element */
 	xfs_buf_t	*bp;
-	int		i, ops;
+	int		i;
 	uint		count;		/* byte count of bwrite */
 	uint		count_init;	/* initial count before roundup */
 	int		roundoff;       /* roundoff to BB or stripe */
 	int		split = 0;	/* split write into two regions */
 	int		error;
-	SPLDECL(s);
 	int		v2 = XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb);
 
 	XFS_STATS_INC(xs_log_writes);
@@ -1415,30 +1426,26 @@
 		 roundoff < BBTOB(1)));
 
 	/* move grant heads by roundoff in sync */
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 	xlog_grant_add_space(log, roundoff);
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 
 	/* put cycle number in every block */
 	xlog_pack_data(log, iclog, roundoff); 
 
 	/* real byte length */
 	if (v2) {
-		INT_SET(iclog->ic_header.h_len, 
-			ARCH_CONVERT,
-			iclog->ic_offset + roundoff);
+		iclog->ic_header.h_len =
+			cpu_to_be32(iclog->ic_offset + roundoff);
 	} else {
-		INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+		iclog->ic_header.h_len =
+			cpu_to_be32(iclog->ic_offset);
 	}
 
-	/* put ops count in correct order */
-	ops = iclog->ic_header.h_num_logops;
-	INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops);
-
 	bp = iclog->ic_bp;
 	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
 	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
-	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)));
+	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(be64_to_cpu(iclog->ic_header.h_lsn)));
 
 	XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
 
@@ -1501,10 +1508,10 @@
 		 * a new cycle.  Watch out for the header magic number
 		 * case, though.
 		 */
-		for (i=0; i<split; i += BBSIZE) {
-			INT_MOD(*(uint *)dptr, ARCH_CONVERT, +1);
-			if (INT_GET(*(uint *)dptr, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM)
-				INT_MOD(*(uint *)dptr, ARCH_CONVERT, +1);
+		for (i = 0; i < split; i += BBSIZE) {
+			be32_add((__be32 *)dptr, 1);
+			if (be32_to_cpu(*(__be32 *)dptr) == XLOG_HEADER_MAGIC_NUM)
+				be32_add((__be32 *)dptr, 1);
 			dptr += BBSIZE;
 		}
 
@@ -1527,14 +1534,13 @@
 /*
  * Deallocate a log structure
  */
-void
+STATIC void
 xlog_dealloc_log(xlog_t *log)
 {
 	xlog_in_core_t	*iclog, *next_iclog;
 	xlog_ticket_t	*tic, *next_tic;
 	int		i;
 
-
 	iclog = log->l_iclog;
 	for (i=0; i<log->l_iclog_bufs; i++) {
 		sv_destroy(&iclog->ic_forcesema);
@@ -1565,7 +1571,7 @@
 		tic = log->l_unmount_free;
 		while (tic) {
 			next_tic = tic->t_next;
-			kmem_free(tic, NBPP);
+			kmem_free(tic, PAGE_SIZE);
 			tic = next_tic;
 		}
 	}
@@ -1592,14 +1598,12 @@
 		       int		record_cnt,
 		       int		copy_bytes)
 {
-	SPLDECL(s);
+	spin_lock(&log->l_icloglock);
 
-	s = LOG_LOCK(log);
-
-	iclog->ic_header.h_num_logops += record_cnt;
+	be32_add(&iclog->ic_header.h_num_logops, record_cnt);
 	iclog->ic_offset += copy_bytes;
 
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 }	/* xlog_state_finish_copy */
 
 
@@ -1752,7 +1756,7 @@
  *	we don't update ic_offset until the end when we know exactly how many
  *	bytes have been written out.
  */
-int
+STATIC int
 xlog_write(xfs_mount_t *	mp,
 	   xfs_log_iovec_t	reg[],
 	   int			nentries,
@@ -1823,7 +1827,7 @@
 
 	/* start_lsn is the first lsn written to. That's all we need. */
 	if (! *start_lsn)
-	    *start_lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
+	    *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn);
 
 	/* This loop writes out as many regions as can fit in the amount
 	 * of space which was allocated by xlog_state_get_iclog_space().
@@ -1839,7 +1843,7 @@
 	     */
 	    if (ticket->t_flags & XLOG_TIC_INITED) {
 		logop_head		= (xlog_op_header_t *)ptr;
-		INT_SET(logop_head->oh_tid, ARCH_CONVERT, ticket->t_tid);
+		logop_head->oh_tid	= cpu_to_be32(ticket->t_tid);
 		logop_head->oh_clientid = ticket->t_clientid;
 		logop_head->oh_len	= 0;
 		logop_head->oh_flags    = XLOG_START_TRANS;
@@ -1853,7 +1857,7 @@
 
 	    /* Copy log operation header directly into data section */
 	    logop_head			= (xlog_op_header_t *)ptr;
-	    INT_SET(logop_head->oh_tid, ARCH_CONVERT, ticket->t_tid);
+	    logop_head->oh_tid		= cpu_to_be32(ticket->t_tid);
 	    logop_head->oh_clientid	= ticket->t_clientid;
 	    logop_head->oh_res2		= 0;
 
@@ -1888,13 +1892,14 @@
 
 	    copy_off = partial_copy_len;
 	    if (need_copy <= iclog->ic_size - log_offset) { /*complete write */
-		INT_SET(logop_head->oh_len, ARCH_CONVERT, copy_len = need_copy);
+	        copy_len = need_copy;
+		logop_head->oh_len = cpu_to_be32(copy_len);
 		if (partial_copy)
 		    logop_head->oh_flags|= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS);
 		partial_copy_len = partial_copy = 0;
 	    } else {					    /* partial write */
 		copy_len = iclog->ic_size - log_offset;
-		INT_SET(logop_head->oh_len, ARCH_CONVERT, copy_len);
+		logop_head->oh_len = cpu_to_be32(copy_len);
 		logop_head->oh_flags |= XLOG_CONTINUE_TRANS;
 		if (partial_copy)
 			logop_head->oh_flags |= XLOG_WAS_CONT_TRANS;
@@ -1992,7 +1997,8 @@
 			 * We don't need to cover the dummy.
 			 */
 			if (!changed &&
-			   (INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT) == XLOG_COVER_OPS)) {
+			   (be32_to_cpu(iclog->ic_header.h_num_logops) ==
+			   		XLOG_COVER_OPS)) {
 				changed = 1;
 			} else {
 				/*
@@ -2060,7 +2066,7 @@
 	lowest_lsn = 0;
 	do {
 	    if (!(lsn_log->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_DIRTY))) {
-		lsn = INT_GET(lsn_log->ic_header.h_lsn, ARCH_CONVERT);
+		lsn = be64_to_cpu(lsn_log->ic_header.h_lsn);
 		if ((lsn && !lowest_lsn) ||
 		    (XFS_LSN_CMP(lsn, lowest_lsn) < 0)) {
 			lowest_lsn = lsn;
@@ -2089,9 +2095,8 @@
 	int		   funcdidcallbacks; /* flag: function did callbacks */
 	int		   repeats;	/* for issuing console warnings if
 					 * looping too many times */
-	SPLDECL(s);
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	first_iclog = iclog = log->l_iclog;
 	ioerrors = 0;
 	funcdidcallbacks = 0;
@@ -2136,7 +2141,7 @@
 				 * to DO_CALLBACK, we will not process it when
 				 * we retry since a previous iclog is in the
 				 * CALLBACK and the state cannot change since
-				 * we are holding the LOG_LOCK.
+				 * we are holding the l_icloglock.
 				 */
 				if (!(iclog->ic_state &
 					(XLOG_STATE_DONE_SYNC |
@@ -2162,11 +2167,9 @@
 				 */
 
 				lowest_lsn = xlog_get_lowest_lsn(log);
-				if (lowest_lsn && (
-					XFS_LSN_CMP(
-						lowest_lsn,
-						INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)
-					)<0)) {
+				if (lowest_lsn &&
+				    XFS_LSN_CMP(lowest_lsn,
+				    		be64_to_cpu(iclog->ic_header.h_lsn)) < 0) {
 					iclog = iclog->ic_next;
 					continue; /* Leave this iclog for
 						   * another thread */
@@ -2174,19 +2177,18 @@
 
 				iclog->ic_state = XLOG_STATE_CALLBACK;
 
-				LOG_UNLOCK(log, s);
+				spin_unlock(&log->l_icloglock);
 
 				/* l_last_sync_lsn field protected by
-				 * GRANT_LOCK. Don't worry about iclog's lsn.
+				 * l_grant_lock. Don't worry about iclog's lsn.
 				 * No one else can be here except us.
 				 */
-				s = GRANT_LOCK(log);
-				ASSERT(XFS_LSN_CMP(
-						log->l_last_sync_lsn,
-						INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)
-					)<=0);
-				log->l_last_sync_lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
-				GRANT_UNLOCK(log, s);
+				spin_lock(&log->l_grant_lock);
+				ASSERT(XFS_LSN_CMP(log->l_last_sync_lsn,
+				       be64_to_cpu(iclog->ic_header.h_lsn)) <= 0);
+				log->l_last_sync_lsn =
+					be64_to_cpu(iclog->ic_header.h_lsn);
+				spin_unlock(&log->l_grant_lock);
 
 				/*
 				 * Keep processing entries in the callback list
@@ -2195,7 +2197,7 @@
 				 * empty and change the state to DIRTY so that
 				 * we don't miss any more callbacks being added.
 				 */
-				s = LOG_LOCK(log);
+				spin_lock(&log->l_icloglock);
 			} else {
 				ioerrors++;
 			}
@@ -2204,14 +2206,14 @@
 			while (cb) {
 				iclog->ic_callback_tail = &(iclog->ic_callback);
 				iclog->ic_callback = NULL;
-				LOG_UNLOCK(log, s);
+				spin_unlock(&log->l_icloglock);
 
 				/* perform callbacks in the order given */
 				for (; cb; cb = cb_next) {
 					cb_next = cb->cb_next;
 					cb->cb_func(cb->cb_arg, aborted);
 				}
-				s = LOG_LOCK(log);
+				spin_lock(&log->l_icloglock);
 				cb = iclog->ic_callback;
 			}
 
@@ -2258,7 +2260,7 @@
 			 *
 			 * SYNCING - i/o completion will go through logs
 			 * DONE_SYNC - interrupt thread should be waiting for
-			 *              LOG_LOCK
+			 *              l_icloglock
 			 * IOERROR - give up hope all ye who enter here
 			 */
 			if (iclog->ic_state == XLOG_STATE_WANT_SYNC ||
@@ -2276,7 +2278,7 @@
 		flushcnt = log->l_flushcnt;
 		log->l_flushcnt = 0;
 	}
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 	while (flushcnt--)
 		vsema(&log->l_flushsema);
 }	/* xlog_state_do_callback */
@@ -2296,15 +2298,14 @@
  * global state machine log lock.  Assume that the calls to cvsema won't
  * take a long time.  At least we know it won't sleep.
  */
-void
+STATIC void
 xlog_state_done_syncing(
 	xlog_in_core_t	*iclog,
 	int		aborted)
 {
 	xlog_t		   *log = iclog->ic_log;
-	SPLDECL(s);
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 
 	ASSERT(iclog->ic_state == XLOG_STATE_SYNCING ||
 	       iclog->ic_state == XLOG_STATE_IOERROR);
@@ -2320,7 +2321,7 @@
 	 */
 	if (iclog->ic_state != XLOG_STATE_IOERROR) {
 		if (--iclog->ic_bwritecnt == 1) {
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 			return;
 		}
 		iclog->ic_state = XLOG_STATE_DONE_SYNC;
@@ -2332,7 +2333,7 @@
 	 * I/O, the others get to wait for the result.
 	 */
 	sv_broadcast(&iclog->ic_writesema);
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 	xlog_state_do_callback(log, aborted, iclog);	/* also cleans log */
 }	/* xlog_state_done_syncing */
 
@@ -2357,7 +2358,7 @@
  *		needs to be incremented, depending on the amount of data which
  *		is copied.
  */
-int
+STATIC int
 xlog_state_get_iclog_space(xlog_t	  *log,
 			   int		  len,
 			   xlog_in_core_t **iclogp,
@@ -2365,23 +2366,22 @@
 			   int		  *continued_write,
 			   int		  *logoffsetp)
 {
-	SPLDECL(s);
 	int		  log_offset;
 	xlog_rec_header_t *head;
 	xlog_in_core_t	  *iclog;
 	int		  error;
 
 restart:
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	if (XLOG_FORCED_SHUTDOWN(log)) {
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		return XFS_ERROR(EIO);
 	}
 
 	iclog = log->l_iclog;
 	if (! (iclog->ic_state == XLOG_STATE_ACTIVE)) {
 		log->l_flushcnt++;
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH);
 		XFS_STATS_INC(xs_log_noiclogs);
 		/* Ensure that log writes happen */
@@ -2404,8 +2404,9 @@
 		xlog_tic_add_region(ticket,
 				    log->l_iclog_hsize,
 				    XLOG_REG_TYPE_LRHEADER);
-		INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
-		ASSIGN_LSN(head->h_lsn, log);
+		head->h_cycle = cpu_to_be32(log->l_curr_cycle);
+		head->h_lsn = cpu_to_be64(
+			xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block));
 		ASSERT(log->l_curr_block >= 0);
 	}
 
@@ -2423,12 +2424,12 @@
 
 		/* If I'm the only one writing to this iclog, sync it to disk */
 		if (iclog->ic_refcnt == 1) {
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 			if ((error = xlog_state_release_iclog(log, iclog)))
 				return error;
 		} else {
 			iclog->ic_refcnt--;
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 		}
 		goto restart;
 	}
@@ -2449,7 +2450,7 @@
 	*iclogp = iclog;
 
 	ASSERT(iclog->ic_offset <= iclog->ic_size);
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 
 	*logoffsetp = log_offset;
 	return 0;
@@ -2467,7 +2468,6 @@
 {
 	int		 free_bytes;
 	int		 need_bytes;
-	SPLDECL(s);
 #ifdef DEBUG
 	xfs_lsn_t	 tail_lsn;
 #endif
@@ -2479,7 +2479,7 @@
 #endif
 
 	/* Is there space or do we need to sleep? */
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 	xlog_trace_loggrant(log, tic, "xlog_grant_log_space: enter");
 
 	/* something is already sleeping; insert new transaction at end */
@@ -2502,7 +2502,7 @@
 		 */
 		xlog_trace_loggrant(log, tic,
 				    "xlog_grant_log_space: wake 1");
-		s = GRANT_LOCK(log);
+		spin_lock(&log->l_grant_lock);
 	}
 	if (tic->t_flags & XFS_LOG_PERM_RESERV)
 		need_bytes = tic->t_unit_res*tic->t_ocnt;
@@ -2524,14 +2524,14 @@
 		sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
 
 		if (XLOG_FORCED_SHUTDOWN(log)) {
-			s = GRANT_LOCK(log);
+			spin_lock(&log->l_grant_lock);
 			goto error_return;
 		}
 
 		xlog_trace_loggrant(log, tic,
 				    "xlog_grant_log_space: wake 2");
 		xlog_grant_push_ail(log->l_mp, need_bytes);
-		s = GRANT_LOCK(log);
+		spin_lock(&log->l_grant_lock);
 		goto redo;
 	} else if (tic->t_flags & XLOG_TIC_IN_Q)
 		xlog_del_ticketq(&log->l_reserve_headq, tic);
@@ -2553,7 +2553,7 @@
 #endif
 	xlog_trace_loggrant(log, tic, "xlog_grant_log_space: exit");
 	xlog_verify_grant_head(log, 1);
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 	return 0;
 
  error_return:
@@ -2567,7 +2567,7 @@
 	 */
 	tic->t_curr_res = 0;
 	tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 	return XFS_ERROR(EIO);
 }	/* xlog_grant_log_space */
 
@@ -2581,7 +2581,6 @@
 xlog_regrant_write_log_space(xlog_t	   *log,
 			     xlog_ticket_t *tic)
 {
-	SPLDECL(s);
 	int		free_bytes, need_bytes;
 	xlog_ticket_t	*ntic;
 #ifdef DEBUG
@@ -2599,7 +2598,7 @@
 		panic("regrant Recovery problem");
 #endif
 
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 	xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: enter");
 
 	if (XLOG_FORCED_SHUTDOWN(log))
@@ -2638,14 +2637,14 @@
 			/* If we're shutting down, this tic is already
 			 * off the queue */
 			if (XLOG_FORCED_SHUTDOWN(log)) {
-				s = GRANT_LOCK(log);
+				spin_lock(&log->l_grant_lock);
 				goto error_return;
 			}
 
 			xlog_trace_loggrant(log, tic,
 				    "xlog_regrant_write_log_space: wake 1");
 			xlog_grant_push_ail(log->l_mp, tic->t_unit_res);
-			s = GRANT_LOCK(log);
+			spin_lock(&log->l_grant_lock);
 		}
 	}
 
@@ -2665,14 +2664,14 @@
 
 		/* If we're shutting down, this tic is already off the queue */
 		if (XLOG_FORCED_SHUTDOWN(log)) {
-			s = GRANT_LOCK(log);
+			spin_lock(&log->l_grant_lock);
 			goto error_return;
 		}
 
 		xlog_trace_loggrant(log, tic,
 				    "xlog_regrant_write_log_space: wake 2");
 		xlog_grant_push_ail(log->l_mp, need_bytes);
-		s = GRANT_LOCK(log);
+		spin_lock(&log->l_grant_lock);
 		goto redo;
 	} else if (tic->t_flags & XLOG_TIC_IN_Q)
 		xlog_del_ticketq(&log->l_write_headq, tic);
@@ -2689,7 +2688,7 @@
 
 	xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit");
 	xlog_verify_grant_head(log, 1);
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 	return 0;
 
 
@@ -2704,7 +2703,7 @@
 	 */
 	tic->t_curr_res = 0;
 	tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 	return XFS_ERROR(EIO);
 }	/* xlog_regrant_write_log_space */
 
@@ -2720,14 +2719,12 @@
 xlog_regrant_reserve_log_space(xlog_t	     *log,
 			       xlog_ticket_t *ticket)
 {
-	SPLDECL(s);
-
 	xlog_trace_loggrant(log, ticket,
 			    "xlog_regrant_reserve_log_space: enter");
 	if (ticket->t_cnt > 0)
 		ticket->t_cnt--;
 
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 	xlog_grant_sub_space(log, ticket->t_curr_res);
 	ticket->t_curr_res = ticket->t_unit_res;
 	xlog_tic_reset_res(ticket);
@@ -2737,7 +2734,7 @@
 
 	/* just return if we still have some of the pre-reserved space */
 	if (ticket->t_cnt > 0) {
-		GRANT_UNLOCK(log, s);
+		spin_unlock(&log->l_grant_lock);
 		return;
 	}
 
@@ -2745,7 +2742,7 @@
 	xlog_trace_loggrant(log, ticket,
 			    "xlog_regrant_reserve_log_space: exit");
 	xlog_verify_grant_head(log, 0);
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 	ticket->t_curr_res = ticket->t_unit_res;
 	xlog_tic_reset_res(ticket);
 }	/* xlog_regrant_reserve_log_space */
@@ -2769,12 +2766,10 @@
 xlog_ungrant_log_space(xlog_t	     *log,
 		       xlog_ticket_t *ticket)
 {
-	SPLDECL(s);
-
 	if (ticket->t_cnt > 0)
 		ticket->t_cnt--;
 
-	s = GRANT_LOCK(log);
+	spin_lock(&log->l_grant_lock);
 	xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter");
 
 	xlog_grant_sub_space(log, ticket->t_curr_res);
@@ -2791,7 +2786,7 @@
 
 	xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit");
 	xlog_verify_grant_head(log, 1);
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 	xfs_log_move_tail(log->l_mp, 1);
 }	/* xlog_ungrant_log_space */
 
@@ -2799,15 +2794,13 @@
 /*
  * Atomically put back used ticket.
  */
-void
+STATIC void
 xlog_state_put_ticket(xlog_t	    *log,
 		      xlog_ticket_t *tic)
 {
-	unsigned long s;
-
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	xlog_ticket_put(log, tic);
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 }	/* xlog_state_put_ticket */
 
 /*
@@ -2819,19 +2812,18 @@
  *
  *
  */
-int
+STATIC int
 xlog_state_release_iclog(xlog_t		*log,
 			 xlog_in_core_t	*iclog)
 {
-	SPLDECL(s);
 	int		sync = 0;	/* do we sync? */
 
 	xlog_assign_tail_lsn(log->l_mp);
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		return XFS_ERROR(EIO);
 	}
 
@@ -2843,12 +2835,12 @@
 	    iclog->ic_state == XLOG_STATE_WANT_SYNC) {
 		sync++;
 		iclog->ic_state = XLOG_STATE_SYNCING;
-		INT_SET(iclog->ic_header.h_tail_lsn, ARCH_CONVERT, log->l_tail_lsn);
+		iclog->ic_header.h_tail_lsn = cpu_to_be64(log->l_tail_lsn);
 		xlog_verify_tail_lsn(log, iclog, log->l_tail_lsn);
 		/* cycle incremented when incrementing curr_block */
 	}
 
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 
 	/*
 	 * We let the log lock go, so it's possible that we hit a log I/O
@@ -2881,7 +2873,7 @@
 	if (!eventual_size)
 		eventual_size = iclog->ic_offset;
 	iclog->ic_state = XLOG_STATE_WANT_SYNC;
-	INT_SET(iclog->ic_header.h_prev_block, ARCH_CONVERT, log->l_prev_block);
+	iclog->ic_header.h_prev_block = cpu_to_be32(log->l_prev_block);
 	log->l_prev_block = log->l_curr_block;
 	log->l_prev_cycle = log->l_curr_cycle;
 
@@ -2939,13 +2931,12 @@
 {
 	xlog_in_core_t	*iclog;
 	xfs_lsn_t	lsn;
-	SPLDECL(s);
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 
 	iclog = log->l_iclog;
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		return XFS_ERROR(EIO);
 	}
 
@@ -2978,15 +2969,15 @@
 				 * the previous sync.
 				 */
 				iclog->ic_refcnt++;
-				lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
+				lsn = be64_to_cpu(iclog->ic_header.h_lsn);
 				xlog_state_switch_iclogs(log, iclog, 0);
-				LOG_UNLOCK(log, s);
+				spin_unlock(&log->l_icloglock);
 
 				if (xlog_state_release_iclog(log, iclog))
 					return XFS_ERROR(EIO);
 				*log_flushed = 1;
-				s = LOG_LOCK(log);
-				if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn &&
+				spin_lock(&log->l_icloglock);
+				if (be64_to_cpu(iclog->ic_header.h_lsn) == lsn &&
 				    iclog->ic_state != XLOG_STATE_DIRTY)
 					goto maybe_sleep;
 				else
@@ -3011,12 +3002,12 @@
 	if (flags & XFS_LOG_SYNC) {
 		/*
 		 * We must check if we're shutting down here, before
-		 * we wait, while we're holding the LOG_LOCK.
+		 * we wait, while we're holding the l_icloglock.
 		 * Then we check again after waking up, in case our
 		 * sleep was disturbed by a bad news.
 		 */
 		if (iclog->ic_state & XLOG_STATE_IOERROR) {
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 			return XFS_ERROR(EIO);
 		}
 		XFS_STATS_INC(xs_log_force_sleep);
@@ -3033,7 +3024,7 @@
 	} else {
 
 no_sleep:
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 	}
 	return 0;
 }	/* xlog_state_sync_all */
@@ -3051,7 +3042,7 @@
  * If filesystem activity goes to zero, the iclog will get flushed only by
  * bdflush().
  */
-int
+STATIC int
 xlog_state_sync(xlog_t	  *log,
 		xfs_lsn_t lsn,
 		uint	  flags,
@@ -3059,26 +3050,24 @@
 {
     xlog_in_core_t	*iclog;
     int			already_slept = 0;
-    SPLDECL(s);
-
 
 try_again:
-    s = LOG_LOCK(log);
+    spin_lock(&log->l_icloglock);
     iclog = log->l_iclog;
 
     if (iclog->ic_state & XLOG_STATE_IOERROR) {
-	    LOG_UNLOCK(log, s);
+	    spin_unlock(&log->l_icloglock);
 	    return XFS_ERROR(EIO);
     }
 
     do {
-	if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) != lsn) {
-	    iclog = iclog->ic_next;
-	    continue;
+	if (be64_to_cpu(iclog->ic_header.h_lsn) != lsn) {
+		iclog = iclog->ic_next;
+		continue;
 	}
 
 	if (iclog->ic_state == XLOG_STATE_DIRTY) {
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		return 0;
 	}
 
@@ -3113,11 +3102,11 @@
 		} else {
 			iclog->ic_refcnt++;
 			xlog_state_switch_iclogs(log, iclog, 0);
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 			if (xlog_state_release_iclog(log, iclog))
 				return XFS_ERROR(EIO);
 			*log_flushed = 1;
-			s = LOG_LOCK(log);
+			spin_lock(&log->l_icloglock);
 		}
 	}
 
@@ -3129,7 +3118,7 @@
 		 * gotten a log write error.
 		 */
 		if (iclog->ic_state & XLOG_STATE_IOERROR) {
-			LOG_UNLOCK(log, s);
+			spin_unlock(&log->l_icloglock);
 			return XFS_ERROR(EIO);
 		}
 		XFS_STATS_INC(xs_log_force_sleep);
@@ -3143,13 +3132,13 @@
 			return XFS_ERROR(EIO);
 		*log_flushed = 1;
 	} else {		/* just return */
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 	}
 	return 0;
 
     } while (iclog != log->l_iclog);
 
-    LOG_UNLOCK(log, s);
+    spin_unlock(&log->l_icloglock);
     return 0;
 }	/* xlog_state_sync */
 
@@ -3158,12 +3147,10 @@
  * Called when we want to mark the current iclog as being ready to sync to
  * disk.
  */
-void
+STATIC void
 xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
 {
-	SPLDECL(s);
-
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 
 	if (iclog->ic_state == XLOG_STATE_ACTIVE) {
 		xlog_state_switch_iclogs(log, iclog, 0);
@@ -3172,7 +3159,7 @@
 			(XLOG_STATE_WANT_SYNC|XLOG_STATE_IOERROR));
 	}
 
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 }	/* xlog_state_want_sync */
 
 
@@ -3193,16 +3180,15 @@
 	xlog_ticket_t	*t_list;
 	xlog_ticket_t	*next;
 	xfs_caddr_t	buf;
-	uint		i = (NBPP / sizeof(xlog_ticket_t)) - 2;
-	SPLDECL(s);
+	uint		i = (PAGE_SIZE / sizeof(xlog_ticket_t)) - 2;
 
 	/*
 	 * The kmem_zalloc may sleep, so we shouldn't be holding the
 	 * global lock.  XXXmiken: may want to use zone allocator.
 	 */
-	buf = (xfs_caddr_t) kmem_zalloc(NBPP, KM_SLEEP);
+	buf = (xfs_caddr_t) kmem_zalloc(PAGE_SIZE, KM_SLEEP);
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 
 	/* Attach 1st ticket to Q, so we can keep track of allocated memory */
 	t_list = (xlog_ticket_t *)buf;
@@ -3231,7 +3217,7 @@
 	}
 	t_list->t_next = NULL;
 	log->l_tail = t_list;
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 }	/* xlog_state_ticket_alloc */
 
 
@@ -3273,7 +3259,7 @@
 /*
  * Grab ticket off freelist or allocation some more
  */
-xlog_ticket_t *
+STATIC xlog_ticket_t *
 xlog_ticket_get(xlog_t		*log,
 		int		unit_bytes,
 		int		cnt,
@@ -3282,15 +3268,14 @@
 {
 	xlog_ticket_t	*tic;
 	uint		num_headers;
-	SPLDECL(s);
 
  alloc:
 	if (log->l_freelist == NULL)
 		xlog_state_ticket_alloc(log);		/* potentially sleep */
 
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	if (log->l_freelist == NULL) {
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 		goto alloc;
 	}
 	tic		= log->l_freelist;
@@ -3298,7 +3283,7 @@
 	if (log->l_freelist == NULL)
 		log->l_tail = NULL;
 	log->l_ticket_cnt--;
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 
 	/*
 	 * Permanent reservations have up to 'cnt'-1 active log operations
@@ -3473,10 +3458,9 @@
 	__uint8_t		clientid;
 	int			len, i, j, k, op_len;
 	int			idx;
-	SPLDECL(s);
 
 	/* check validity of iclog pointers */
-	s = LOG_LOCK(log);
+	spin_lock(&log->l_icloglock);
 	icptr = log->l_iclog;
 	for (i=0; i < log->l_iclog_bufs; i++) {
 		if (icptr == NULL)
@@ -3485,21 +3469,21 @@
 	}
 	if (icptr != log->l_iclog)
 		xlog_panic("xlog_verify_iclog: corrupt iclog ring");
-	LOG_UNLOCK(log, s);
+	spin_unlock(&log->l_icloglock);
 
 	/* check log magic numbers */
-	ptr = (xfs_caddr_t) &(iclog->ic_header);
-	if (INT_GET(*(uint *)ptr, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM)
+	if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM)
 		xlog_panic("xlog_verify_iclog: invalid magic num");
 
-	for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&(iclog->ic_header))+count;
+	ptr = (xfs_caddr_t) &iclog->ic_header;
+	for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count;
 	     ptr += BBSIZE) {
-		if (INT_GET(*(uint *)ptr, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM)
+		if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM)
 			xlog_panic("xlog_verify_iclog: unexpected magic num");
 	}
 
 	/* check fields */
-	len = INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT);
+	len = be32_to_cpu(iclog->ic_header.h_num_logops);
 	ptr = iclog->ic_datap;
 	base_ptr = ptr;
 	ophead = (xlog_op_header_t *)ptr;
@@ -3517,9 +3501,11 @@
 			if (idx >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE)) {
 				j = idx / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
 				k = idx % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-				clientid = GET_CLIENT_ID(xhdr[j].hic_xheader.xh_cycle_data[k], ARCH_CONVERT);
+				clientid = xlog_get_client_id(
+					xhdr[j].hic_xheader.xh_cycle_data[k]);
 			} else {
-				clientid = GET_CLIENT_ID(iclog->ic_header.h_cycle_data[idx], ARCH_CONVERT);
+				clientid = xlog_get_client_id(
+					iclog->ic_header.h_cycle_data[idx]);
 			}
 		}
 		if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
@@ -3531,16 +3517,16 @@
 		field_offset = (__psint_t)
 			       ((xfs_caddr_t)&(ophead->oh_len) - base_ptr);
 		if (syncing == B_FALSE || (field_offset & 0x1ff)) {
-			op_len = INT_GET(ophead->oh_len, ARCH_CONVERT);
+			op_len = be32_to_cpu(ophead->oh_len);
 		} else {
 			idx = BTOBBT((__psint_t)&ophead->oh_len -
 				    (__psint_t)iclog->ic_datap);
 			if (idx >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE)) {
 				j = idx / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
 				k = idx % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-				op_len = INT_GET(xhdr[j].hic_xheader.xh_cycle_data[k], ARCH_CONVERT);
+				op_len = be32_to_cpu(xhdr[j].hic_xheader.xh_cycle_data[k]);
 			} else {
-				op_len = INT_GET(iclog->ic_header.h_cycle_data[idx], ARCH_CONVERT);
+				op_len = be32_to_cpu(iclog->ic_header.h_cycle_data[idx]);
 			}
 		}
 		ptr += sizeof(xlog_op_header_t) + op_len;
@@ -3549,7 +3535,7 @@
 #endif
 
 /*
- * Mark all iclogs IOERROR. LOG_LOCK is held by the caller.
+ * Mark all iclogs IOERROR. l_icloglock is held by the caller.
  */
 STATIC int
 xlog_state_ioerror(
@@ -3597,8 +3583,6 @@
 	xlog_t		*log;
 	int		retval;
 	int		dummy;
-	SPLDECL(s);
-	SPLDECL(s2);
 
 	log = mp->m_log;
 
@@ -3627,8 +3611,8 @@
 	 * before we mark the filesystem SHUTDOWN and wake
 	 * everybody up to tell the bad news.
 	 */
-	s = GRANT_LOCK(log);
-	s2 = LOG_LOCK(log);
+	spin_lock(&log->l_grant_lock);
+	spin_lock(&log->l_icloglock);
 	mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
 	XFS_BUF_DONE(mp->m_sb_bp);
 	/*
@@ -3644,7 +3628,7 @@
 	 */
 	if (logerror)
 		retval = xlog_state_ioerror(log);
-	LOG_UNLOCK(log, s2);
+	spin_unlock(&log->l_icloglock);
 
 	/*
 	 * We don't want anybody waiting for log reservations
@@ -3667,7 +3651,7 @@
 			tic = tic->t_next;
 		} while (tic != log->l_write_headq);
 	}
-	GRANT_UNLOCK(log, s);
+	spin_unlock(&log->l_grant_lock);
 
 	if (! (log->l_iclog->ic_state & XLOG_STATE_IOERROR)) {
 		ASSERT(!logerror);
@@ -3676,9 +3660,9 @@
 		 * log down completely.
 		 */
 		xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy);
-		s2 = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 		retval = xlog_state_ioerror(log);
-		LOG_UNLOCK(log, s2);
+		spin_unlock(&log->l_icloglock);
 	}
 	/*
 	 * Wake up everybody waiting on xfs_log_force.
@@ -3691,13 +3675,13 @@
 	{
 		xlog_in_core_t	*iclog;
 
-		s = LOG_LOCK(log);
+		spin_lock(&log->l_icloglock);
 		iclog = log->l_iclog;
 		do {
 			ASSERT(iclog->ic_callback == 0);
 			iclog = iclog->ic_next;
 		} while (iclog != log->l_iclog);
-		LOG_UNLOCK(log, s);
+		spin_unlock(&log->l_icloglock);
 	}
 #endif
 	/* return non-zero if log IOERROR transition had already happened */
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index ebbe93f..4cdac04 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -22,8 +22,9 @@
 
 #define CYCLE_LSN(lsn) ((uint)((lsn)>>32))
 #define BLOCK_LSN(lsn) ((uint)(lsn))
+
 /* this is used in a spot where we might otherwise double-endian-flip */
-#define CYCLE_LSN_DISK(lsn) (((uint *)&(lsn))[0])
+#define CYCLE_LSN_DISK(lsn) (((__be32 *)&(lsn))[0])
 
 #ifdef __KERNEL__
 /*
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 752f964..e008233 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -55,33 +55,22 @@
 	BTOBB(XLOG_MAX_ICLOGS << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
 	 XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
 
-/*
- *  set lsns
- */
 
-#define ASSIGN_ANY_LSN_HOST(lsn,cycle,block)  \
-    { \
-	(lsn) = ((xfs_lsn_t)(cycle)<<32)|(block); \
-    }
-#define ASSIGN_ANY_LSN_DISK(lsn,cycle,block)  \
-    { \
-	INT_SET(((uint *)&(lsn))[0], ARCH_CONVERT, (cycle)); \
-	INT_SET(((uint *)&(lsn))[1], ARCH_CONVERT, (block)); \
-    }
-#define ASSIGN_LSN(lsn,log) \
-    ASSIGN_ANY_LSN_DISK(lsn,(log)->l_curr_cycle,(log)->l_curr_block);
+static inline xfs_lsn_t xlog_assign_lsn(uint cycle, uint block)
+{
+	return ((xfs_lsn_t)cycle << 32) | block;
+}
 
-#define XLOG_SET(f,b)		(((f) & (b)) == (b))
-
-#define GET_CYCLE(ptr, arch) \
-    (INT_GET(*(uint *)(ptr), arch) == XLOG_HEADER_MAGIC_NUM ? \
-	 INT_GET(*((uint *)(ptr)+1), arch) : \
-	 INT_GET(*(uint *)(ptr), arch) \
-    )
+static inline uint xlog_get_cycle(char *ptr)
+{
+	if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM)
+		return be32_to_cpu(*((__be32 *)ptr + 1));
+	else
+		return be32_to_cpu(*(__be32 *)ptr);
+}
 
 #define BLK_AVG(blk1, blk2)	((blk1+blk2) >> 1)
 
-
 #ifdef __KERNEL__
 
 /*
@@ -96,19 +85,10 @@
  *
  * this has endian issues, of course.
  */
-
-#ifndef XFS_NATIVE_HOST
-#define GET_CLIENT_ID(i,arch) \
-    ((i) & 0xff)
-#else
-#define GET_CLIENT_ID(i,arch) \
-    ((i) >> 24)
-#endif
-
-#define GRANT_LOCK(log)		mutex_spinlock(&(log)->l_grant_lock)
-#define GRANT_UNLOCK(log, s)	mutex_spinunlock(&(log)->l_grant_lock, s)
-#define LOG_LOCK(log)		mutex_spinlock(&(log)->l_icloglock)
-#define LOG_UNLOCK(log, s)	mutex_spinunlock(&(log)->l_icloglock, s)
+static inline uint xlog_get_client_id(__be32 i)
+{
+	return be32_to_cpu(i) >> 24;
+}
 
 #define xlog_panic(args...)	cmn_err(CE_PANIC, ## args)
 #define xlog_exit(args...)	cmn_err(CE_PANIC, ## args)
@@ -285,11 +265,11 @@
 
 
 typedef struct xlog_op_header {
-	xlog_tid_t oh_tid;	/* transaction id of operation	:  4 b */
-	int	   oh_len;	/* bytes in data region		:  4 b */
-	__uint8_t  oh_clientid;	/* who sent me this		:  1 b */
-	__uint8_t  oh_flags;	/*				:  1 b */
-	ushort	   oh_res2;	/* 32 bit align			:  2 b */
+	__be32	   oh_tid;	/* transaction id of operation	:  4 b */
+	__be32	   oh_len;	/* bytes in data region		:  4 b */
+	__u8	   oh_clientid;	/* who sent me this		:  1 b */
+	__u8	   oh_flags;	/*				:  1 b */
+	__u16	   oh_res2;	/* 32 bit align			:  2 b */
 } xlog_op_header_t;
 
 
@@ -307,25 +287,25 @@
 #endif
 
 typedef struct xlog_rec_header {
-	uint	  h_magicno;	/* log record (LR) identifier		:  4 */
-	uint	  h_cycle;	/* write cycle of log			:  4 */
-	int	  h_version;	/* LR version				:  4 */
-	int	  h_len;	/* len in bytes; should be 64-bit aligned: 4 */
-	xfs_lsn_t h_lsn;	/* lsn of this LR			:  8 */
-	xfs_lsn_t h_tail_lsn;	/* lsn of 1st LR w/ buffers not committed: 8 */
-	uint	  h_chksum;	/* may not be used; non-zero if used	:  4 */
-	int	  h_prev_block; /* block number to previous LR		:  4 */
-	int	  h_num_logops;	/* number of log operations in this LR	:  4 */
-	uint	  h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];
+	__be32	  h_magicno;	/* log record (LR) identifier		:  4 */
+	__be32	  h_cycle;	/* write cycle of log			:  4 */
+	__be32	  h_version;	/* LR version				:  4 */
+	__be32	  h_len;	/* len in bytes; should be 64-bit aligned: 4 */
+	__be64	  h_lsn;	/* lsn of this LR			:  8 */
+	__be64	  h_tail_lsn;	/* lsn of 1st LR w/ buffers not committed: 8 */
+	__be32	  h_chksum;	/* may not be used; non-zero if used	:  4 */
+	__be32	  h_prev_block; /* block number to previous LR		:  4 */
+	__be32	  h_num_logops;	/* number of log operations in this LR	:  4 */
+	__be32	  h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];
 	/* new fields */
-	int       h_fmt;        /* format of log record                 :  4 */
-	uuid_t    h_fs_uuid;    /* uuid of FS                           : 16 */
-	int       h_size;	/* iclog size				:  4 */
+	__be32    h_fmt;        /* format of log record                 :  4 */
+	uuid_t	  h_fs_uuid;    /* uuid of FS                           : 16 */
+	__be32	  h_size;	/* iclog size				:  4 */
 } xlog_rec_header_t;
 
 typedef struct xlog_rec_ext_header {
-	uint	  xh_cycle;	/* write cycle of log			: 4 */
-	uint	  xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /*	: 256 */
+	__be32	  xh_cycle;	/* write cycle of log			: 4 */
+	__be32	  xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /*	: 256 */
 } xlog_rec_ext_header_t;
 
 #ifdef __KERNEL__
@@ -415,7 +395,7 @@
 	xlog_ticket_t		*l_unmount_free;/* kmem_free these addresses */
 	xlog_ticket_t		*l_tail;        /* free list of tickets */
 	xlog_in_core_t		*l_iclog;       /* head log queue	*/
-	lock_t			l_icloglock;    /* grab to change iclog state */
+	spinlock_t		l_icloglock;    /* grab to change iclog state */
 	xfs_lsn_t		l_tail_lsn;     /* lsn of 1st LR with unflushed
 						 * buffers */
 	xfs_lsn_t		l_last_sync_lsn;/* lsn of last LR on disk */
@@ -439,7 +419,7 @@
 	char			*l_iclog_bak[XLOG_MAX_ICLOGS];
 
 	/* The following block of fields are changed while holding grant_lock */
-	lock_t			l_grant_lock;
+	spinlock_t		l_grant_lock;
 	xlog_ticket_t		*l_reserve_headq;
 	xlog_ticket_t		*l_write_headq;
 	int			l_grant_reserve_cycle;
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 851eca8..b82d5d4 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -198,7 +198,7 @@
 	cmn_err(CE_DEBUG, "    log : uuid = ");
 	for (b = 0; b < 16; b++)
 		cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]);
-	cmn_err(CE_DEBUG, ", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT));
+	cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt));
 }
 #else
 #define xlog_header_check_dump(mp, head)
@@ -212,14 +212,14 @@
 	xfs_mount_t		*mp,
 	xlog_rec_header_t	*head)
 {
-	ASSERT(INT_GET(head->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
+	ASSERT(be32_to_cpu(head->h_magicno) == XLOG_HEADER_MAGIC_NUM);
 
 	/*
 	 * IRIX doesn't write the h_fmt field and leaves it zeroed
 	 * (XLOG_FMT_UNKNOWN). This stops us from trying to recover
 	 * a dirty log created in IRIX.
 	 */
-	if (unlikely(INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT)) {
+	if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) {
 		xlog_warn(
 	"XFS: dirty log written in incompatible format - can't recover");
 		xlog_header_check_dump(mp, head);
@@ -245,7 +245,7 @@
 	xfs_mount_t		*mp,
 	xlog_rec_header_t	*head)
 {
-	ASSERT(INT_GET(head->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
+	ASSERT(be32_to_cpu(head->h_magicno) == XLOG_HEADER_MAGIC_NUM);
 
 	if (uuid_is_nil(&head->h_fs_uuid)) {
 		/*
@@ -293,7 +293,7 @@
  * Note that the algorithm can not be perfect because the disk will not
  * necessarily be perfect.
  */
-int
+STATIC int
 xlog_find_cycle_start(
 	xlog_t		*log,
 	xfs_buf_t	*bp,
@@ -311,7 +311,7 @@
 		if ((error = xlog_bread(log, mid_blk, 1, bp)))
 			return error;
 		offset = xlog_align(log, mid_blk, 1, bp);
-		mid_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+		mid_cycle = xlog_get_cycle(offset);
 		if (mid_cycle == cycle) {
 			*last_blk = mid_blk;
 			/* last_half_cycle == mid_cycle */
@@ -371,7 +371,7 @@
 
 		buf = xlog_align(log, i, bcount, bp);
 		for (j = 0; j < bcount; j++) {
-			cycle = GET_CYCLE(buf, ARCH_CONVERT);
+			cycle = xlog_get_cycle(buf);
 			if (cycle == stop_on_cycle_no) {
 				*new_blk = i+j;
 				goto out;
@@ -447,8 +447,7 @@
 
 		head = (xlog_rec_header_t *)offset;
 
-		if (XLOG_HEADER_MAGIC_NUM ==
-		    INT_GET(head->h_magicno, ARCH_CONVERT))
+		if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(head->h_magicno))
 			break;
 
 		if (!smallmem)
@@ -480,7 +479,7 @@
 	 * record do we update last_blk.
 	 */
 	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-		uint	h_size = INT_GET(head->h_size, ARCH_CONVERT);
+		uint	h_size = be32_to_cpu(head->h_size);
 
 		xhdrs = h_size / XLOG_HEADER_CYCLE_SIZE;
 		if (h_size % XLOG_HEADER_CYCLE_SIZE)
@@ -489,8 +488,8 @@
 		xhdrs = 1;
 	}
 
-	if (*last_blk - i + extra_bblks
-			!= BTOBB(INT_GET(head->h_len, ARCH_CONVERT)) + xhdrs)
+	if (*last_blk - i + extra_bblks !=
+	    BTOBB(be32_to_cpu(head->h_len)) + xhdrs)
 		*last_blk = i;
 
 out:
@@ -550,13 +549,13 @@
 	if ((error = xlog_bread(log, 0, 1, bp)))
 		goto bp_err;
 	offset = xlog_align(log, 0, 1, bp);
-	first_half_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+	first_half_cycle = xlog_get_cycle(offset);
 
 	last_blk = head_blk = log_bbnum - 1;	/* get cycle # of last block */
 	if ((error = xlog_bread(log, last_blk, 1, bp)))
 		goto bp_err;
 	offset = xlog_align(log, last_blk, 1, bp);
-	last_half_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+	last_half_cycle = xlog_get_cycle(offset);
 	ASSERT(last_half_cycle != 0);
 
 	/*
@@ -808,7 +807,7 @@
 		if ((error = xlog_bread(log, 0, 1, bp)))
 			goto bread_err;
 		offset = xlog_align(log, 0, 1, bp);
-		if (GET_CYCLE(offset, ARCH_CONVERT) == 0) {
+		if (xlog_get_cycle(offset) == 0) {
 			*tail_blk = 0;
 			/* leave all other log inited values alone */
 			goto exit;
@@ -823,8 +822,7 @@
 		if ((error = xlog_bread(log, i, 1, bp)))
 			goto bread_err;
 		offset = xlog_align(log, i, 1, bp);
-		if (XLOG_HEADER_MAGIC_NUM ==
-		    INT_GET(*(uint *)offset, ARCH_CONVERT)) {
+		if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
 			found = 1;
 			break;
 		}
@@ -841,7 +839,7 @@
 				goto bread_err;
 			offset = xlog_align(log, i, 1, bp);
 			if (XLOG_HEADER_MAGIC_NUM ==
-			    INT_GET(*(uint*)offset, ARCH_CONVERT)) {
+			    be32_to_cpu(*(__be32 *)offset)) {
 				found = 2;
 				break;
 			}
@@ -855,7 +853,7 @@
 
 	/* find blk_no of tail of log */
 	rhead = (xlog_rec_header_t *)offset;
-	*tail_blk = BLOCK_LSN(INT_GET(rhead->h_tail_lsn, ARCH_CONVERT));
+	*tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn));
 
 	/*
 	 * Reset log values according to the state of the log when we
@@ -869,11 +867,11 @@
 	 */
 	log->l_prev_block = i;
 	log->l_curr_block = (int)*head_blk;
-	log->l_curr_cycle = INT_GET(rhead->h_cycle, ARCH_CONVERT);
+	log->l_curr_cycle = be32_to_cpu(rhead->h_cycle);
 	if (found == 2)
 		log->l_curr_cycle++;
-	log->l_tail_lsn = INT_GET(rhead->h_tail_lsn, ARCH_CONVERT);
-	log->l_last_sync_lsn = INT_GET(rhead->h_lsn, ARCH_CONVERT);
+	log->l_tail_lsn = be64_to_cpu(rhead->h_tail_lsn);
+	log->l_last_sync_lsn = be64_to_cpu(rhead->h_lsn);
 	log->l_grant_reserve_cycle = log->l_curr_cycle;
 	log->l_grant_reserve_bytes = BBTOB(log->l_curr_block);
 	log->l_grant_write_cycle = log->l_curr_cycle;
@@ -891,8 +889,8 @@
 	 * unmount record rather than the block after it.
 	 */
 	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-		int	h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
-		int	h_version = INT_GET(rhead->h_version, ARCH_CONVERT);
+		int	h_size = be32_to_cpu(rhead->h_size);
+		int	h_version = be32_to_cpu(rhead->h_version);
 
 		if ((h_version & XLOG_VERSION_2) &&
 		    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
@@ -906,10 +904,10 @@
 		hblks = 1;
 	}
 	after_umount_blk = (i + hblks + (int)
-		BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT))) % log->l_logBBsize;
+		BTOBB(be32_to_cpu(rhead->h_len))) % log->l_logBBsize;
 	tail_lsn = log->l_tail_lsn;
 	if (*head_blk == after_umount_blk &&
-	    INT_GET(rhead->h_num_logops, ARCH_CONVERT) == 1) {
+	    be32_to_cpu(rhead->h_num_logops) == 1) {
 		umount_data_blk = (i + hblks) % log->l_logBBsize;
 		if ((error = xlog_bread(log, umount_data_blk, 1, bp))) {
 			goto bread_err;
@@ -922,10 +920,12 @@
 			 * log records will point recovery to after the
 			 * current unmount record.
 			 */
-			ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, log->l_curr_cycle,
-					after_umount_blk);
-			ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
-					after_umount_blk);
+			log->l_tail_lsn =
+				xlog_assign_lsn(log->l_curr_cycle,
+						after_umount_blk);
+			log->l_last_sync_lsn =
+				xlog_assign_lsn(log->l_curr_cycle,
+						after_umount_blk);
 			*tail_blk = after_umount_blk;
 
 			/*
@@ -986,7 +986,7 @@
  *	-1 => use *blk_no as the first block of the log
  *	>0 => error has occurred
  */
-int
+STATIC int
 xlog_find_zeroed(
 	xlog_t		*log,
 	xfs_daddr_t	*blk_no)
@@ -1007,7 +1007,7 @@
 	if ((error = xlog_bread(log, 0, 1, bp)))
 		goto bp_err;
 	offset = xlog_align(log, 0, 1, bp);
-	first_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+	first_cycle = xlog_get_cycle(offset);
 	if (first_cycle == 0) {		/* completely zeroed log */
 		*blk_no = 0;
 		xlog_put_bp(bp);
@@ -1018,7 +1018,7 @@
 	if ((error = xlog_bread(log, log_bbnum-1, 1, bp)))
 		goto bp_err;
 	offset = xlog_align(log, log_bbnum-1, 1, bp);
-	last_cycle = GET_CYCLE(offset, ARCH_CONVERT);
+	last_cycle = xlog_get_cycle(offset);
 	if (last_cycle != 0) {		/* log completely written to */
 		xlog_put_bp(bp);
 		return 0;
@@ -1098,13 +1098,13 @@
 	xlog_rec_header_t	*recp = (xlog_rec_header_t *)buf;
 
 	memset(buf, 0, BBSIZE);
-	INT_SET(recp->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
-	INT_SET(recp->h_cycle, ARCH_CONVERT, cycle);
-	INT_SET(recp->h_version, ARCH_CONVERT,
+	recp->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
+	recp->h_cycle = cpu_to_be32(cycle);
+	recp->h_version = cpu_to_be32(
 			XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? 2 : 1);
-	ASSIGN_ANY_LSN_DISK(recp->h_lsn, cycle, block);
-	ASSIGN_ANY_LSN_DISK(recp->h_tail_lsn, tail_cycle, tail_block);
-	INT_SET(recp->h_fmt, ARCH_CONVERT, XLOG_FMT);
+	recp->h_lsn = cpu_to_be64(xlog_assign_lsn(cycle, block));
+	recp->h_tail_lsn = cpu_to_be64(xlog_assign_lsn(tail_cycle, tail_block));
+	recp->h_fmt = cpu_to_be32(XLOG_FMT);
 	memcpy(&recp->h_fs_uuid, &log->l_mp->m_sb.sb_uuid, sizeof(uuid_t));
 }
 
@@ -2211,7 +2211,7 @@
 	 * overlap with future reads of those inodes.
 	 */
 	if (XFS_DINODE_MAGIC ==
-	    INT_GET(*((__uint16_t *)(xfs_buf_offset(bp, 0))), ARCH_CONVERT) &&
+	    be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) &&
 	    (XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize,
 			(__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) {
 		XFS_BUF_STALE(bp);
@@ -2581,8 +2581,7 @@
 	/*
 	 * This type of quotas was turned off, so ignore this record.
 	 */
-	type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
-			(XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
+	type = recddq->d_flags & (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
 	ASSERT(type);
 	if (log->l_quotaoffs_flag & type)
 		return (0);
@@ -2660,7 +2659,6 @@
 	xfs_mount_t		*mp;
 	xfs_efi_log_item_t	*efip;
 	xfs_efi_log_format_t	*efi_formatp;
-	SPLDECL(s);
 
 	if (pass == XLOG_RECOVER_PASS1) {
 		return 0;
@@ -2678,11 +2676,11 @@
 	efip->efi_next_extent = efi_formatp->efi_nextents;
 	efip->efi_flags |= XFS_EFI_COMMITTED;
 
-	AIL_LOCK(mp,s);
+	spin_lock(&mp->m_ail_lock);
 	/*
 	 * xfs_trans_update_ail() drops the AIL lock.
 	 */
-	xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
+	xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn);
 	return 0;
 }
 
@@ -2707,7 +2705,6 @@
 	xfs_log_item_t		*lip;
 	int			gen;
 	__uint64_t		efi_id;
-	SPLDECL(s);
 
 	if (pass == XLOG_RECOVER_PASS1) {
 		return;
@@ -2725,7 +2722,7 @@
 	 * in the AIL.
 	 */
 	mp = log->l_mp;
-	AIL_LOCK(mp,s);
+	spin_lock(&mp->m_ail_lock);
 	lip = xfs_trans_first_ail(mp, &gen);
 	while (lip != NULL) {
 		if (lip->li_type == XFS_LI_EFI) {
@@ -2735,22 +2732,14 @@
 				 * xfs_trans_delete_ail() drops the
 				 * AIL lock.
 				 */
-				xfs_trans_delete_ail(mp, lip, s);
-				break;
+				xfs_trans_delete_ail(mp, lip);
+				xfs_efi_item_free(efip);
+				return;
 			}
 		}
 		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
 	}
-
-	/*
-	 * If we found it, then free it up.  If it wasn't there, it
-	 * must have been overwritten in the log.  Oh well.
-	 */
-	if (lip != NULL) {
-		xfs_efi_item_free(efip);
-	} else {
-		AIL_UNLOCK(mp, s);
-	}
+	spin_unlock(&mp->m_ail_lock);
 }
 
 /*
@@ -2897,8 +2886,8 @@
 	unsigned long		hash;
 	uint			flags;
 
-	lp = dp + INT_GET(rhead->h_len, ARCH_CONVERT);
-	num_logops = INT_GET(rhead->h_num_logops, ARCH_CONVERT);
+	lp = dp + be32_to_cpu(rhead->h_len);
+	num_logops = be32_to_cpu(rhead->h_num_logops);
 
 	/* check the log format matches our own - else we can't recover */
 	if (xlog_header_check_recover(log->l_mp, rhead))
@@ -2915,15 +2904,20 @@
 			ASSERT(0);
 			return (XFS_ERROR(EIO));
 		}
-		tid = INT_GET(ohead->oh_tid, ARCH_CONVERT);
+		tid = be32_to_cpu(ohead->oh_tid);
 		hash = XLOG_RHASH(tid);
 		trans = xlog_recover_find_tid(rhash[hash], tid);
 		if (trans == NULL) {		   /* not found; add new tid */
 			if (ohead->oh_flags & XLOG_START_TRANS)
 				xlog_recover_new_tid(&rhash[hash], tid,
-					INT_GET(rhead->h_lsn, ARCH_CONVERT));
+					be64_to_cpu(rhead->h_lsn));
 		} else {
-			ASSERT(dp+INT_GET(ohead->oh_len, ARCH_CONVERT) <= lp);
+			if (dp + be32_to_cpu(ohead->oh_len) > lp) {
+				xlog_warn(
+			"XFS: xlog_recover_process_data: bad length");
+				WARN_ON(1);
+				return (XFS_ERROR(EIO));
+			}
 			flags = ohead->oh_flags & ~XLOG_END_TRANS;
 			if (flags & XLOG_WAS_CONT_TRANS)
 				flags &= ~XLOG_CONTINUE_TRANS;
@@ -2937,8 +2931,7 @@
 				break;
 			case XLOG_WAS_CONT_TRANS:
 				error = xlog_recover_add_to_cont_trans(trans,
-						dp, INT_GET(ohead->oh_len,
-							ARCH_CONVERT));
+						dp, be32_to_cpu(ohead->oh_len));
 				break;
 			case XLOG_START_TRANS:
 				xlog_warn(
@@ -2949,8 +2942,7 @@
 			case 0:
 			case XLOG_CONTINUE_TRANS:
 				error = xlog_recover_add_to_trans(trans,
-						dp, INT_GET(ohead->oh_len,
-							ARCH_CONVERT));
+						dp, be32_to_cpu(ohead->oh_len));
 				break;
 			default:
 				xlog_warn(
@@ -2962,7 +2954,7 @@
 			if (error)
 				return error;
 		}
-		dp += INT_GET(ohead->oh_len, ARCH_CONVERT);
+		dp += be32_to_cpu(ohead->oh_len);
 		num_logops--;
 	}
 	return 0;
@@ -3075,10 +3067,9 @@
 	xfs_efi_log_item_t	*efip;
 	int			gen;
 	xfs_mount_t		*mp;
-	SPLDECL(s);
 
 	mp = log->l_mp;
-	AIL_LOCK(mp,s);
+	spin_lock(&mp->m_ail_lock);
 
 	lip = xfs_trans_first_ail(mp, &gen);
 	while (lip != NULL) {
@@ -3099,12 +3090,12 @@
 			continue;
 		}
 
-		AIL_UNLOCK(mp, s);
+		spin_unlock(&mp->m_ail_lock);
 		xlog_recover_process_efi(mp, efip);
-		AIL_LOCK(mp,s);
+		spin_lock(&mp->m_ail_lock);
 		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
 	}
-	AIL_UNLOCK(mp, s);
+	spin_unlock(&mp->m_ail_lock);
 }
 
 /*
@@ -3315,16 +3306,16 @@
 	int		size)
 {
 	int		i;
-	uint		*up;
+	__be32		*up;
 	uint		chksum = 0;
 
-	up = (uint *)iclog->ic_datap;
+	up = (__be32 *)iclog->ic_datap;
 	/* divide length by 4 to get # words */
 	for (i = 0; i < (size >> 2); i++) {
-		chksum ^= INT_GET(*up, ARCH_CONVERT);
+		chksum ^= be32_to_cpu(*up);
 		up++;
 	}
-	INT_SET(iclog->ic_header.h_chksum, ARCH_CONVERT, chksum);
+	iclog->ic_header.h_chksum = cpu_to_be32(chksum);
 }
 #else
 #define xlog_pack_data_checksum(log, iclog, size)
@@ -3341,7 +3332,7 @@
 {
 	int			i, j, k;
 	int			size = iclog->ic_offset + roundoff;
-	uint			cycle_lsn;
+	__be32			cycle_lsn;
 	xfs_caddr_t		dp;
 	xlog_in_core_2_t	*xhdr;
 
@@ -3352,8 +3343,8 @@
 	dp = iclog->ic_datap;
 	for (i = 0; i < BTOBB(size) &&
 		i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
-		iclog->ic_header.h_cycle_data[i] = *(uint *)dp;
-		*(uint *)dp = cycle_lsn;
+		iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
+		*(__be32 *)dp = cycle_lsn;
 		dp += BBSIZE;
 	}
 
@@ -3362,8 +3353,8 @@
 		for ( ; i < BTOBB(size); i++) {
 			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
 			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-			xhdr[j].hic_xheader.xh_cycle_data[k] = *(uint *)dp;
-			*(uint *)dp = cycle_lsn;
+			xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
+			*(__be32 *)dp = cycle_lsn;
 			dp += BBSIZE;
 		}
 
@@ -3380,21 +3371,21 @@
 	xfs_caddr_t		dp,
 	xlog_t			*log)
 {
-	uint			*up = (uint *)dp;
+	__be32			*up = (__be32 *)dp;
 	uint			chksum = 0;
 	int			i;
 
 	/* divide length by 4 to get # words */
-	for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) {
-		chksum ^= INT_GET(*up, ARCH_CONVERT);
+	for (i=0; i < be32_to_cpu(rhead->h_len) >> 2; i++) {
+		chksum ^= be32_to_cpu(*up);
 		up++;
 	}
-	if (chksum != INT_GET(rhead->h_chksum, ARCH_CONVERT)) {
+	if (chksum != be32_to_cpu(rhead->h_chksum)) {
 	    if (rhead->h_chksum ||
 		((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
 		    cmn_err(CE_DEBUG,
 			"XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n",
-			    INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum);
+			    be32_to_cpu(rhead->h_chksum), chksum);
 		    cmn_err(CE_DEBUG,
 "XFS: Disregard message if filesystem was created with non-DEBUG kernel");
 		    if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
@@ -3418,18 +3409,18 @@
 	int			i, j, k;
 	xlog_in_core_2_t	*xhdr;
 
-	for (i = 0; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)) &&
+	for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
 		  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
-		*(uint *)dp = *(uint *)&rhead->h_cycle_data[i];
+		*(__be32 *)dp = *(__be32 *)&rhead->h_cycle_data[i];
 		dp += BBSIZE;
 	}
 
 	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
 		xhdr = (xlog_in_core_2_t *)rhead;
-		for ( ; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)); i++) {
+		for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) {
 			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
 			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-			*(uint *)dp = xhdr[j].hic_xheader.xh_cycle_data[k];
+			*(__be32 *)dp = xhdr[j].hic_xheader.xh_cycle_data[k];
 			dp += BBSIZE;
 		}
 	}
@@ -3445,24 +3436,21 @@
 {
 	int			hlen;
 
-	if (unlikely(
-	    (INT_GET(rhead->h_magicno, ARCH_CONVERT) !=
-			XLOG_HEADER_MAGIC_NUM))) {
+	if (unlikely(be32_to_cpu(rhead->h_magicno) != XLOG_HEADER_MAGIC_NUM)) {
 		XFS_ERROR_REPORT("xlog_valid_rec_header(1)",
 				XFS_ERRLEVEL_LOW, log->l_mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	if (unlikely(
 	    (!rhead->h_version ||
-	    (INT_GET(rhead->h_version, ARCH_CONVERT) &
-			(~XLOG_VERSION_OKBITS)) != 0))) {
+	    (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
 		xlog_warn("XFS: %s: unrecognised log version (%d).",
-			__FUNCTION__, INT_GET(rhead->h_version, ARCH_CONVERT));
+			__FUNCTION__, be32_to_cpu(rhead->h_version));
 		return XFS_ERROR(EIO);
 	}
 
 	/* LR body must have data or it wouldn't have been written */
-	hlen = INT_GET(rhead->h_len, ARCH_CONVERT);
+	hlen = be32_to_cpu(rhead->h_len);
 	if (unlikely( hlen <= 0 || hlen > INT_MAX )) {
 		XFS_ERROR_REPORT("xlog_valid_rec_header(2)",
 				XFS_ERRLEVEL_LOW, log->l_mp);
@@ -3522,9 +3510,8 @@
 		error = xlog_valid_rec_header(log, rhead, tail_blk);
 		if (error)
 			goto bread_err1;
-		h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
-		if ((INT_GET(rhead->h_version, ARCH_CONVERT)
-				& XLOG_VERSION_2) &&
+		h_size = be32_to_cpu(rhead->h_size);
+		if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) &&
 		    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
 			hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
 			if (h_size % XLOG_HEADER_CYCLE_SIZE)
@@ -3561,7 +3548,7 @@
 				goto bread_err2;
 
 			/* blocks in data section */
-			bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
+			bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
 			error = xlog_bread(log, blk_no + hblks, bblks, dbp);
 			if (error)
 				goto bread_err2;
@@ -3636,7 +3623,7 @@
 			if (error)
 				goto bread_err2;
 
-			bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
+			bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
 			blk_no += hblks;
 
 			/* Read in data for log record */
@@ -3707,7 +3694,7 @@
 			error = xlog_valid_rec_header(log, rhead, blk_no);
 			if (error)
 				goto bread_err2;
-			bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
+			bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
 			if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
 				goto bread_err2;
 			offset = xlog_align(log, blk_no+hblks, bblks, dbp);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index ebdb76d..6409b37 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -136,15 +136,9 @@
 		mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;
 	}
 
-	AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");
-	spinlock_init(&mp->m_sb_lock, "xfs_sb");
+	spin_lock_init(&mp->m_sb_lock);
 	mutex_init(&mp->m_ilock);
 	mutex_init(&mp->m_growlock);
-	/*
-	 * Initialize the AIL.
-	 */
-	xfs_trans_ail_init(mp);
-
 	atomic_set(&mp->m_active_trans, 0);
 
 	return mp;
@@ -171,7 +165,7 @@
 			  sizeof(xfs_perag_t) * mp->m_sb.sb_agcount);
 	}
 
-	AIL_LOCK_DESTROY(&mp->m_ail_lock);
+	spinlock_destroy(&mp->m_ail_lock);
 	spinlock_destroy(&mp->m_sb_lock);
 	mutex_destroy(&mp->m_ilock);
 	mutex_destroy(&mp->m_growlock);
@@ -616,7 +610,7 @@
 	int	i;
 
 	mp->m_agfrotor = mp->m_agirotor = 0;
-	spinlock_init(&mp->m_agirotor_lock, "m_agirotor_lock");
+	spin_lock_init(&mp->m_agirotor_lock);
 	mp->m_maxagi = mp->m_sb.sb_agcount;
 	mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
 	mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
@@ -696,7 +690,6 @@
 	uint64_t	bfreelst = 0;
 	uint64_t	btree = 0;
 	int		error;
-	int		s;
 
 	for (index = 0; index < agcount; index++) {
 		/*
@@ -721,11 +714,11 @@
 	/*
 	 * Overwrite incore superblock counters with just-read data
 	 */
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	sbp->sb_ifree = ifree;
 	sbp->sb_icount = ialloc;
 	sbp->sb_fdblocks = bfree + bfreelst + btree;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	/* Fixup the per-cpu counters as well. */
 	xfs_icsb_reinit_counters(mp);
@@ -734,49 +727,13 @@
 }
 
 /*
- * xfs_mountfs
- *
- * This function does the following on an initial mount of a file system:
- *	- reads the superblock from disk and init the mount struct
- *	- if we're a 32-bit kernel, do a size check on the superblock
- *		so we don't mount terabyte filesystems
- *	- init mount struct realtime fields
- *	- allocate inode hash table for fs
- *	- init directory manager
- *	- perform recovery and init the log manager
+ * Update alignment values based on mount options and sb values
  */
-int
-xfs_mountfs(
-	xfs_mount_t	*mp,
-	int		mfsi_flags)
+STATIC int
+xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags)
 {
-	xfs_buf_t	*bp;
 	xfs_sb_t	*sbp = &(mp->m_sb);
-	xfs_inode_t	*rip;
-	bhv_vnode_t	*rvp = NULL;
-	int		readio_log, writeio_log;
-	xfs_daddr_t	d;
-	__uint64_t	resblks;
-	__int64_t	update_flags;
-	uint		quotamount, quotaflags;
-	int		agno;
-	int		uuid_mounted = 0;
-	int		error = 0;
 
-	if (mp->m_sb_bp == NULL) {
-		if ((error = xfs_readsb(mp, mfsi_flags))) {
-			return error;
-		}
-	}
-	xfs_mount_common(mp, sbp);
-
-	/*
-	 * Check if sb_agblocks is aligned at stripe boundary
-	 * If sb_agblocks is NOT aligned turn off m_dalign since
-	 * allocator alignment is within an ag, therefore ag has
-	 * to be aligned at stripe boundary.
-	 */
-	update_flags = 0LL;
 	if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) {
 		/*
 		 * If stripe unit and stripe width are not multiples
@@ -787,8 +744,7 @@
 			if (mp->m_flags & XFS_MOUNT_RETERR) {
 				cmn_err(CE_WARN,
 					"XFS: alignment check 1 failed");
-				error = XFS_ERROR(EINVAL);
-				goto error1;
+				return XFS_ERROR(EINVAL);
 			}
 			mp->m_dalign = mp->m_swidth = 0;
 		} else {
@@ -798,8 +754,7 @@
 			mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
 			if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
 				if (mp->m_flags & XFS_MOUNT_RETERR) {
-					error = XFS_ERROR(EINVAL);
-					goto error1;
+					return XFS_ERROR(EINVAL);
 				}
 				xfs_fs_cmn_err(CE_WARN, mp,
 "stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)",
@@ -816,8 +771,7 @@
 "stripe alignment turned off: sunit(%d) less than bsize(%d)",
                                         	mp->m_dalign,
 						mp->m_blockmask +1);
-					error = XFS_ERROR(EINVAL);
-					goto error1;
+					return XFS_ERROR(EINVAL);
 				}
 				mp->m_swidth = 0;
 			}
@@ -830,11 +784,11 @@
 		if (XFS_SB_VERSION_HASDALIGN(sbp)) {
 			if (sbp->sb_unit != mp->m_dalign) {
 				sbp->sb_unit = mp->m_dalign;
-				update_flags |= XFS_SB_UNIT;
+				*update_flags |= XFS_SB_UNIT;
 			}
 			if (sbp->sb_width != mp->m_swidth) {
 				sbp->sb_width = mp->m_swidth;
-				update_flags |= XFS_SB_WIDTH;
+				*update_flags |= XFS_SB_WIDTH;
 			}
 		}
 	} else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
@@ -843,49 +797,45 @@
 			mp->m_swidth = sbp->sb_width;
 	}
 
-	xfs_alloc_compute_maxlevels(mp);
-	xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
-	xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
-	xfs_ialloc_compute_maxlevels(mp);
+	return 0;
+}
+
+/*
+ * Set the maximum inode count for this filesystem
+ */
+STATIC void
+xfs_set_maxicount(xfs_mount_t *mp)
+{
+	xfs_sb_t	*sbp = &(mp->m_sb);
+	__uint64_t	icount;
 
 	if (sbp->sb_imax_pct) {
-		__uint64_t	icount;
-
-		/* Make sure the maximum inode count is a multiple of the
-		 * units we allocate inodes in.
+		/*
+		 * Make sure the maximum inode count is a multiple
+		 * of the units we allocate inodes in.
 		 */
-
 		icount = sbp->sb_dblocks * sbp->sb_imax_pct;
 		do_div(icount, 100);
 		do_div(icount, mp->m_ialloc_blks);
 		mp->m_maxicount = (icount * mp->m_ialloc_blks)  <<
 				   sbp->sb_inopblog;
-	} else
+	} else {
 		mp->m_maxicount = 0;
-
-	mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
-
-	/*
-	 * XFS uses the uuid from the superblock as the unique
-	 * identifier for fsid.  We can not use the uuid from the volume
-	 * since a single partition filesystem is identical to a single
-	 * partition volume/filesystem.
-	 */
-	if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
-	    (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
-		if (xfs_uuid_mount(mp)) {
-			error = XFS_ERROR(EINVAL);
-			goto error1;
-		}
-		uuid_mounted=1;
 	}
+}
 
-	/*
-	 * Set the default minimum read and write sizes unless
-	 * already specified in a mount option.
-	 * We use smaller I/O sizes when the file system
-	 * is being used for NFS service (wsync mount option).
-	 */
+/*
+ * Set the default minimum read and write sizes unless
+ * already specified in a mount option.
+ * We use smaller I/O sizes when the file system
+ * is being used for NFS service (wsync mount option).
+ */
+STATIC void
+xfs_set_rw_sizes(xfs_mount_t *mp)
+{
+	xfs_sb_t	*sbp = &(mp->m_sb);
+	int		readio_log, writeio_log;
+
 	if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
 		if (mp->m_flags & XFS_MOUNT_WSYNC) {
 			readio_log = XFS_WSYNC_READIO_LOG;
@@ -911,17 +861,14 @@
 		mp->m_writeio_log = writeio_log;
 	}
 	mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
+}
 
-	/*
-	 * Set the inode cluster size.
-	 * This may still be overridden by the file system
-	 * block size if it is larger than the chosen cluster size.
-	 */
-	mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
-
-	/*
-	 * Set whether we're using inode alignment.
-	 */
+/*
+ * Set whether we're using inode alignment.
+ */
+STATIC void
+xfs_set_inoalignment(xfs_mount_t *mp)
+{
 	if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) &&
 	    mp->m_sb.sb_inoalignmt >=
 	    XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
@@ -937,14 +884,22 @@
 		mp->m_sinoalign = mp->m_dalign;
 	else
 		mp->m_sinoalign = 0;
-	/*
-	 * Check that the data (and log if separate) are an ok size.
-	 */
+}
+
+/*
+ * Check that the data (and log if separate) are an ok size.
+ */
+STATIC int
+xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags)
+{
+	xfs_buf_t	*bp;
+	xfs_daddr_t	d;
+	int		error;
+
 	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
 	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
 		cmn_err(CE_WARN, "XFS: size check 1 failed");
-		error = XFS_ERROR(E2BIG);
-		goto error1;
+		return XFS_ERROR(E2BIG);
 	}
 	error = xfs_read_buf(mp, mp->m_ddev_targp,
 			     d - XFS_FSS_TO_BB(mp, 1),
@@ -953,10 +908,9 @@
 		xfs_buf_relse(bp);
 	} else {
 		cmn_err(CE_WARN, "XFS: size check 2 failed");
-		if (error == ENOSPC) {
+		if (error == ENOSPC)
 			error = XFS_ERROR(E2BIG);
-		}
-		goto error1;
+		return error;
 	}
 
 	if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) &&
@@ -964,8 +918,7 @@
 		d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
 		if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
 			cmn_err(CE_WARN, "XFS: size check 3 failed");
-			error = XFS_ERROR(E2BIG);
-			goto error1;
+			return XFS_ERROR(E2BIG);
 		}
 		error = xfs_read_buf(mp, mp->m_logdev_targp,
 				     d - XFS_FSB_TO_BB(mp, 1),
@@ -974,17 +927,111 @@
 			xfs_buf_relse(bp);
 		} else {
 			cmn_err(CE_WARN, "XFS: size check 3 failed");
-			if (error == ENOSPC) {
+			if (error == ENOSPC)
 				error = XFS_ERROR(E2BIG);
-			}
-			goto error1;
+			return error;
 		}
 	}
+	return 0;
+}
+
+/*
+ * xfs_mountfs
+ *
+ * This function does the following on an initial mount of a file system:
+ *	- reads the superblock from disk and init the mount struct
+ *	- if we're a 32-bit kernel, do a size check on the superblock
+ *		so we don't mount terabyte filesystems
+ *	- init mount struct realtime fields
+ *	- allocate inode hash table for fs
+ *	- init directory manager
+ *	- perform recovery and init the log manager
+ */
+int
+xfs_mountfs(
+	xfs_mount_t	*mp,
+	int		mfsi_flags)
+{
+	xfs_sb_t	*sbp = &(mp->m_sb);
+	xfs_inode_t	*rip;
+	bhv_vnode_t	*rvp = NULL;
+	__uint64_t	resblks;
+	__int64_t	update_flags = 0LL;
+	uint		quotamount, quotaflags;
+	int		agno;
+	int		uuid_mounted = 0;
+	int		error = 0;
+
+	if (mp->m_sb_bp == NULL) {
+		error = xfs_readsb(mp, mfsi_flags);
+		if (error)
+			return error;
+	}
+	xfs_mount_common(mp, sbp);
+
+	/*
+	 * Check if sb_agblocks is aligned at stripe boundary
+	 * If sb_agblocks is NOT aligned turn off m_dalign since
+	 * allocator alignment is within an ag, therefore ag has
+	 * to be aligned at stripe boundary.
+	 */
+	error = xfs_update_alignment(mp, mfsi_flags, &update_flags);
+	if (error)
+		goto error1;
+
+	xfs_alloc_compute_maxlevels(mp);
+	xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
+	xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
+	xfs_ialloc_compute_maxlevels(mp);
+
+	xfs_set_maxicount(mp);
+
+	mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
+
+	/*
+	 * XFS uses the uuid from the superblock as the unique
+	 * identifier for fsid.  We can not use the uuid from the volume
+	 * since a single partition filesystem is identical to a single
+	 * partition volume/filesystem.
+	 */
+	if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
+	    (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
+		if (xfs_uuid_mount(mp)) {
+			error = XFS_ERROR(EINVAL);
+			goto error1;
+		}
+		uuid_mounted=1;
+	}
+
+	/*
+	 * Set the minimum read and write sizes
+	 */
+	xfs_set_rw_sizes(mp);
+
+	/*
+	 * Set the inode cluster size.
+	 * This may still be overridden by the file system
+	 * block size if it is larger than the chosen cluster size.
+	 */
+	mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
+
+	/*
+	 * Set inode alignment fields
+	 */
+	xfs_set_inoalignment(mp);
+
+	/*
+	 * Check that the data (and log if separate) are an ok size.
+	 */
+	error = xfs_check_sizes(mp, mfsi_flags);
+	if (error)
+		goto error1;
 
 	/*
 	 * Initialize realtime fields in the mount structure
 	 */
-	if ((error = xfs_rtmount_init(mp))) {
+	error = xfs_rtmount_init(mp);
+	if (error) {
 		cmn_err(CE_WARN, "XFS: RT mount failed");
 		goto error1;
 	}
@@ -1102,7 +1149,8 @@
 	/*
 	 * Initialize realtime inode pointers in the mount structure
 	 */
-	if ((error = xfs_rtmount_inodes(mp))) {
+	error = xfs_rtmount_inodes(mp);
+	if (error) {
 		/*
 		 * Free up the root inode.
 		 */
@@ -1120,7 +1168,8 @@
 	/*
 	 * Initialise the XFS quota management subsystem for this mount
 	 */
-	if ((error = XFS_QM_INIT(mp, &quotamount, &quotaflags)))
+	error = XFS_QM_INIT(mp, &quotamount, &quotaflags);
+	if (error)
 		goto error4;
 
 	/*
@@ -1137,7 +1186,8 @@
 	/*
 	 * Complete the quota initialisation, post-log-replay component.
 	 */
-	if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags)))
+	error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags);
+	if (error)
 		goto error4;
 
 	/*
@@ -1255,7 +1305,6 @@
 #if defined(DEBUG) || defined(INDUCE_IO_ERROR)
 	xfs_errortag_clearall(mp, 0);
 #endif
-	XFS_IODONE(mp);
 	xfs_mount_free(mp);
 	return 0;
 }
@@ -1441,7 +1490,7 @@
  * Fields are not allowed to dip below zero, so if the delta would
  * do this do not apply it and return EINVAL.
  *
- * The SB_LOCK must be held when this routine is called.
+ * The m_sb_lock must be held when this routine is called.
  */
 int
 xfs_mod_incore_sb_unlocked(
@@ -1606,7 +1655,7 @@
 /*
  * xfs_mod_incore_sb() is used to change a field in the in-core
  * superblock structure by the specified delta.  This modification
- * is protected by the SB_LOCK.  Just use the xfs_mod_incore_sb_unlocked()
+ * is protected by the m_sb_lock.  Just use the xfs_mod_incore_sb_unlocked()
  * routine to do the work.
  */
 int
@@ -1616,7 +1665,6 @@
 	int64_t		delta,
 	int		rsvd)
 {
-	unsigned long	s;
 	int	status;
 
 	/* check for per-cpu counters */
@@ -1633,9 +1681,9 @@
 		/* FALLTHROUGH */
 #endif
 	default:
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-		XFS_SB_UNLOCK(mp, s);
+		spin_unlock(&mp->m_sb_lock);
 		break;
 	}
 
@@ -1656,7 +1704,6 @@
 int
 xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
 {
-	unsigned long	s;
 	int		status=0;
 	xfs_mod_sb_t	*msbp;
 
@@ -1664,10 +1711,10 @@
 	 * Loop through the array of mod structures and apply each
 	 * individually.  If any fail, then back out all those
 	 * which have already been applied.  Do all of this within
-	 * the scope of the SB_LOCK so that all of the changes will
+	 * the scope of the m_sb_lock so that all of the changes will
 	 * be atomic.
 	 */
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	msbp = &msb[0];
 	for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) {
 		/*
@@ -1681,11 +1728,11 @@
 		case XFS_SBS_IFREE:
 		case XFS_SBS_FDBLOCKS:
 			if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-				XFS_SB_UNLOCK(mp, s);
+				spin_unlock(&mp->m_sb_lock);
 				status = xfs_icsb_modify_counters(mp,
 							msbp->msb_field,
 							msbp->msb_delta, rsvd);
-				s = XFS_SB_LOCK(mp);
+				spin_lock(&mp->m_sb_lock);
 				break;
 			}
 			/* FALLTHROUGH */
@@ -1719,12 +1766,12 @@
 			case XFS_SBS_IFREE:
 			case XFS_SBS_FDBLOCKS:
 				if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-					XFS_SB_UNLOCK(mp, s);
+					spin_unlock(&mp->m_sb_lock);
 					status = xfs_icsb_modify_counters(mp,
 							msbp->msb_field,
 							-(msbp->msb_delta),
 							rsvd);
-					s = XFS_SB_LOCK(mp);
+					spin_lock(&mp->m_sb_lock);
 					break;
 				}
 				/* FALLTHROUGH */
@@ -1740,7 +1787,7 @@
 			msbp--;
 		}
 	}
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 	return status;
 }
 
@@ -1888,12 +1935,12 @@
  *
  * Locking rules:
  *
- * 	1. XFS_SB_LOCK() before picking up per-cpu locks
+ * 	1. m_sb_lock before picking up per-cpu locks
  * 	2. per-cpu locks always picked up via for_each_online_cpu() order
- * 	3. accurate counter sync requires XFS_SB_LOCK + per cpu locks
+ * 	3. accurate counter sync requires m_sb_lock + per cpu locks
  * 	4. modifying per-cpu counters requires holding per-cpu lock
- * 	5. modifying global counters requires holding XFS_SB_LOCK
- *	6. enabling or disabling a counter requires holding the XFS_SB_LOCK
+ * 	5. modifying global counters requires holding m_sb_lock
+ *	6. enabling or disabling a counter requires holding the m_sb_lock 
  *	   and _none_ of the per-cpu locks.
  *
  * Disabled counters are only ever re-enabled by a balance operation
@@ -1920,7 +1967,6 @@
 {
 	xfs_icsb_cnts_t *cntp;
 	xfs_mount_t	*mp;
-	int		s;
 
 	mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
 	cntp = (xfs_icsb_cnts_t *)
@@ -1946,7 +1992,7 @@
 		 * count into the total on the global superblock and
 		 * re-enable the counters. */
 		xfs_icsb_lock(mp);
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
 		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
 		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
@@ -1963,7 +2009,7 @@
 					 XFS_ICSB_SB_LOCKED, 0);
 		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS,
 					 XFS_ICSB_SB_LOCKED, 0);
-		XFS_SB_UNLOCK(mp, s);
+		spin_unlock(&mp->m_sb_lock);
 		xfs_icsb_unlock(mp);
 		break;
 	}
@@ -2194,11 +2240,10 @@
 	int		flags)
 {
 	xfs_icsb_cnts_t	cnt;
-	int		s;
 
 	/* Pass 1: lock all counters */
 	if ((flags & XFS_ICSB_SB_LOCKED) == 0)
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 
 	xfs_icsb_count(mp, &cnt, flags);
 
@@ -2211,7 +2256,7 @@
 		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
 
 	if ((flags & XFS_ICSB_SB_LOCKED) == 0)
-		XFS_SB_UNLOCK(mp, s);
+		spin_unlock(&mp->m_sb_lock);
 }
 
 /*
@@ -2252,11 +2297,10 @@
 {
 	uint64_t	count, resid;
 	int		weight = num_online_cpus();
-	int		s;
 	uint64_t	min = (uint64_t)min_per_cpu;
 
 	if (!(flags & XFS_ICSB_SB_LOCKED))
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 
 	/* disable counter and sync counter */
 	xfs_icsb_disable_counter(mp, field);
@@ -2290,10 +2334,10 @@
 	xfs_icsb_enable_counter(mp, field, count, resid);
 out:
 	if (!(flags & XFS_ICSB_SB_LOCKED))
-		XFS_SB_UNLOCK(mp, s);
+		spin_unlock(&mp->m_sb_lock);
 }
 
-int
+STATIC int
 xfs_icsb_modify_counters(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field,
@@ -2302,7 +2346,7 @@
 {
 	xfs_icsb_cnts_t	*icsbp;
 	long long	lcounter;	/* long counter for 64 bit fields */
-	int		cpu, ret = 0, s;
+	int		cpu, ret = 0;
 
 	might_sleep();
 again:
@@ -2380,15 +2424,15 @@
 	 * running atomically here, we know a rebalance cannot
 	 * be in progress. Hence we can go straight to operating
 	 * on the global superblock. We do not call xfs_mod_incore_sb()
-	 * here even though we need to get the SB_LOCK. Doing so
+	 * here even though we need to get the m_sb_lock. Doing so
 	 * will cause us to re-enter this function and deadlock.
-	 * Hence we get the SB_LOCK ourselves and then call
+	 * Hence we get the m_sb_lock ourselves and then call
 	 * xfs_mod_incore_sb_unlocked() as the unlocked path operates
 	 * directly on the global counters.
 	 */
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	/*
 	 * Now that we've modified the global superblock, we
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index c618f7c..f7c620e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -56,20 +56,12 @@
 struct log;
 struct xfs_mount_args;
 struct xfs_inode;
-struct xfs_iocore;
 struct xfs_bmbt_irec;
 struct xfs_bmap_free;
 struct xfs_extdelta;
 struct xfs_swapext;
 struct xfs_mru_cache;
 
-#define	AIL_LOCK_T		lock_t
-#define	AIL_LOCKINIT(x,y)	spinlock_init(x,y)
-#define	AIL_LOCK_DESTROY(x)	spinlock_destroy(x)
-#define	AIL_LOCK(mp,s)		s=mutex_spinlock(&(mp)->m_ail_lock)
-#define	AIL_UNLOCK(mp,s)	mutex_spinunlock(&(mp)->m_ail_lock, s)
-
-
 /*
  * Prototypes and functions for the Data Migration subsystem.
  */
@@ -196,105 +188,6 @@
 #define XFS_QM_QUOTACTL(mp, cmd, id, addr) \
 	(*(mp)->m_qm_ops->xfs_quotactl)(mp, cmd, id, addr)
 
-
-/*
- * Prototypes and functions for I/O core modularization.
- */
-
-typedef int		(*xfs_ioinit_t)(struct xfs_mount *,
-				struct xfs_mount_args *, int);
-typedef int		(*xfs_bmapi_t)(struct xfs_trans *, void *,
-				xfs_fileoff_t, xfs_filblks_t, int,
-				xfs_fsblock_t *, xfs_extlen_t,
-				struct xfs_bmbt_irec *, int *,
-				struct xfs_bmap_free *, struct xfs_extdelta *);
-typedef int		(*xfs_bunmapi_t)(struct xfs_trans *,
-				void *, xfs_fileoff_t,
-				xfs_filblks_t, int, xfs_extnum_t,
-				xfs_fsblock_t *, struct xfs_bmap_free *,
-				struct xfs_extdelta *, int *);
-typedef int		(*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
-typedef int		(*xfs_iomap_write_direct_t)(
-				void *, xfs_off_t, size_t, int,
-				struct xfs_bmbt_irec *, int *, int);
-typedef int		(*xfs_iomap_write_delay_t)(
-				void *, xfs_off_t, size_t, int,
-				struct xfs_bmbt_irec *, int *);
-typedef int		(*xfs_iomap_write_allocate_t)(
-				void *, xfs_off_t, size_t,
-				struct xfs_bmbt_irec *, int *);
-typedef int		(*xfs_iomap_write_unwritten_t)(
-				void *, xfs_off_t, size_t);
-typedef uint		(*xfs_lck_map_shared_t)(void *);
-typedef void		(*xfs_lock_t)(void *, uint);
-typedef void		(*xfs_lock_demote_t)(void *, uint);
-typedef int		(*xfs_lock_nowait_t)(void *, uint);
-typedef void		(*xfs_unlk_t)(void *, unsigned int);
-typedef xfs_fsize_t	(*xfs_size_t)(void *);
-typedef xfs_fsize_t	(*xfs_iodone_t)(struct xfs_mount *);
-typedef int		(*xfs_swap_extents_t)(void *, void *,
-				struct xfs_swapext*);
-
-typedef struct xfs_ioops {
-	xfs_ioinit_t			xfs_ioinit;
-	xfs_bmapi_t			xfs_bmapi_func;
-	xfs_bunmapi_t			xfs_bunmapi_func;
-	xfs_bmap_eof_t			xfs_bmap_eof_func;
-	xfs_iomap_write_direct_t	xfs_iomap_write_direct;
-	xfs_iomap_write_delay_t		xfs_iomap_write_delay;
-	xfs_iomap_write_allocate_t	xfs_iomap_write_allocate;
-	xfs_iomap_write_unwritten_t	xfs_iomap_write_unwritten;
-	xfs_lock_t			xfs_ilock;
-	xfs_lck_map_shared_t		xfs_lck_map_shared;
-	xfs_lock_demote_t		xfs_ilock_demote;
-	xfs_lock_nowait_t		xfs_ilock_nowait;
-	xfs_unlk_t			xfs_unlock;
-	xfs_size_t			xfs_size_func;
-	xfs_iodone_t			xfs_iodone;
-	xfs_swap_extents_t		xfs_swap_extents_func;
-} xfs_ioops_t;
-
-#define XFS_IOINIT(mp, args, flags) \
-	(*(mp)->m_io_ops.xfs_ioinit)(mp, args, flags)
-#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \
-	(*(mp)->m_io_ops.xfs_bmapi_func) \
-		(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta)
-#define XFS_BUNMAPI(mp, trans,io,bno,len,f,nexts,first,flist,delta,done) \
-	(*(mp)->m_io_ops.xfs_bunmapi_func) \
-		(trans,(io)->io_obj,bno,len,f,nexts,first,flist,delta,done)
-#define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \
-	(*(mp)->m_io_ops.xfs_bmap_eof_func) \
-		((io)->io_obj, endoff, whichfork, eof)
-#define XFS_IOMAP_WRITE_DIRECT(mp, io, offset, count, flags, mval, nmap, found)\
-	(*(mp)->m_io_ops.xfs_iomap_write_direct) \
-		((io)->io_obj, offset, count, flags, mval, nmap, found)
-#define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \
-	(*(mp)->m_io_ops.xfs_iomap_write_delay) \
-		((io)->io_obj, offset, count, flags, mval, nmap)
-#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, mval, nmap) \
-	(*(mp)->m_io_ops.xfs_iomap_write_allocate) \
-		((io)->io_obj, offset, count, mval, nmap)
-#define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \
-	(*(mp)->m_io_ops.xfs_iomap_write_unwritten) \
-		((io)->io_obj, offset, count)
-#define XFS_LCK_MAP_SHARED(mp, io) \
-	(*(mp)->m_io_ops.xfs_lck_map_shared)((io)->io_obj)
-#define XFS_ILOCK(mp, io, mode) \
-	(*(mp)->m_io_ops.xfs_ilock)((io)->io_obj, mode)
-#define XFS_ILOCK_NOWAIT(mp, io, mode) \
-	(*(mp)->m_io_ops.xfs_ilock_nowait)((io)->io_obj, mode)
-#define XFS_IUNLOCK(mp, io, mode) \
-	(*(mp)->m_io_ops.xfs_unlock)((io)->io_obj, mode)
-#define XFS_ILOCK_DEMOTE(mp, io, mode) \
-	(*(mp)->m_io_ops.xfs_ilock_demote)((io)->io_obj, mode)
-#define XFS_SIZE(mp, io) \
-	(*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
-#define XFS_IODONE(mp) \
-	(*(mp)->m_io_ops.xfs_iodone)(mp)
-#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \
-	(*(mp)->m_io_ops.xfs_swap_extents_func) \
-		((io)->io_obj, (tio)->io_obj, sxp)
-
 #ifdef HAVE_PERCPU_SB
 
 /*
@@ -326,14 +219,20 @@
 #define xfs_icsb_sync_counters_flags(mp, flags)	do { } while (0)
 #endif
 
+typedef struct xfs_ail {
+	xfs_ail_entry_t		xa_ail;
+	uint			xa_gen;
+	struct task_struct	*xa_task;
+	xfs_lsn_t		xa_target;
+} xfs_ail_t;
+
 typedef struct xfs_mount {
 	struct super_block	*m_super;
 	xfs_tid_t		m_tid;		/* next unused tid for fs */
-	AIL_LOCK_T		m_ail_lock;	/* fs AIL mutex */
-	xfs_ail_entry_t		m_ail;		/* fs active log item list */
-	uint			m_ail_gen;	/* fs AIL generation count */
+	spinlock_t		m_ail_lock;	/* fs AIL mutex */
+	xfs_ail_t		m_ail;		/* fs active log item list */
 	xfs_sb_t		m_sb;		/* copy of fs superblock */
-	lock_t			m_sb_lock;	/* sb counter mutex */
+	spinlock_t		m_sb_lock;	/* sb counter lock */
 	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
 	char			*m_fsname;	/* filesystem name */
 	int			m_fsname_len;	/* strlen of fs name */
@@ -342,7 +241,7 @@
 	int			m_bsize;	/* fs logical block size */
 	xfs_agnumber_t		m_agfrotor;	/* last ag where space found */
 	xfs_agnumber_t		m_agirotor;	/* last ag dir inode alloced */
-	lock_t			m_agirotor_lock;/* .. and lock protecting it */
+	spinlock_t		m_agirotor_lock;/* .. and lock protecting it */
 	xfs_agnumber_t		m_maxagi;	/* highest inode alloc group */
 	struct xfs_inode	*m_inodes;	/* active inode list */
 	struct list_head	m_del_inodes;	/* inodes to reclaim */
@@ -423,7 +322,6 @@
 						 * hash table */
 	struct xfs_dmops	*m_dm_ops;	/* vector of DMI ops */
 	struct xfs_qmops	*m_qm_ops;	/* vector of XQM ops */
-	struct xfs_ioops	m_io_ops;	/* vector of I/O ops */
 	atomic_t		m_active_trans;	/* number trans frozen */
 #ifdef HAVE_PERCPU_SB
 	xfs_icsb_cnts_t		*m_sb_cnts;	/* per-cpu superblock counters */
@@ -610,8 +508,6 @@
 
 #define	XFS_MOUNT_ILOCK(mp)	mutex_lock(&((mp)->m_ilock))
 #define	XFS_MOUNT_IUNLOCK(mp)	mutex_unlock(&((mp)->m_ilock))
-#define	XFS_SB_LOCK(mp)		mutex_spinlock(&(mp)->m_sb_lock)
-#define	XFS_SB_UNLOCK(mp,s)	mutex_spinunlock(&(mp)->m_sb_lock,(s))
 
 extern xfs_mount_t *xfs_mount_init(void);
 extern void	xfs_mod_sb(xfs_trans_t *, __int64_t);
@@ -646,7 +542,6 @@
 extern void	xfs_qmops_put(struct xfs_mount *);
 
 extern struct xfs_dmops xfs_dmcore_xfs;
-extern struct xfs_ioops xfs_iocore_xfs;
 
 extern int	xfs_init(void);
 extern void	xfs_cleanup(void);
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
index e0b358c..a0b2c0a 100644
--- a/fs/xfs/xfs_mru_cache.c
+++ b/fs/xfs/xfs_mru_cache.c
@@ -225,10 +225,14 @@
  * list need to be deleted.  For each element this involves removing it from the
  * data store, removing it from the reap list, calling the client's free
  * function and deleting the element from the element zone.
+ *
+ * We get called holding the mru->lock, which we drop and then reacquire.
+ * Sparse need special help with this to tell it we know what we are doing.
  */
 STATIC void
 _xfs_mru_cache_clear_reap_list(
-	xfs_mru_cache_t		*mru)
+	xfs_mru_cache_t		*mru) __releases(mru->lock) __acquires(mru->lock)
+
 {
 	xfs_mru_cache_elem_t	*elem, *next;
 	struct list_head	tmp;
@@ -245,7 +249,7 @@
 		 */
 		list_move(&elem->list_node, &tmp);
 	}
-	mutex_spinunlock(&mru->lock, 0);
+	spin_unlock(&mru->lock);
 
 	list_for_each_entry_safe(elem, next, &tmp, list_node) {
 
@@ -259,7 +263,7 @@
 		kmem_zone_free(xfs_mru_elem_zone, elem);
 	}
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 }
 
 /*
@@ -280,7 +284,7 @@
 	if (!mru || !mru->lists)
 		return;
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 	next = _xfs_mru_cache_migrate(mru, jiffies);
 	_xfs_mru_cache_clear_reap_list(mru);
 
@@ -294,7 +298,7 @@
 		queue_delayed_work(xfs_mru_reap_wq, &mru->work, next);
 	}
 
-	mutex_spinunlock(&mru->lock, 0);
+	spin_unlock(&mru->lock);
 }
 
 int
@@ -368,7 +372,7 @@
 	 */
 	INIT_RADIX_TREE(&mru->store, GFP_ATOMIC);
 	INIT_LIST_HEAD(&mru->reap_list);
-	spinlock_init(&mru->lock, "xfs_mru_cache");
+	spin_lock_init(&mru->lock);
 	INIT_DELAYED_WORK(&mru->work, _xfs_mru_cache_reap);
 
 	mru->grp_time  = grp_time;
@@ -398,17 +402,17 @@
 	if (!mru || !mru->lists)
 		return;
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 	if (mru->queued) {
-		mutex_spinunlock(&mru->lock, 0);
+		spin_unlock(&mru->lock);
 		cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
-		mutex_spinlock(&mru->lock);
+		spin_lock(&mru->lock);
 	}
 
 	_xfs_mru_cache_migrate(mru, jiffies + mru->grp_count * mru->grp_time);
 	_xfs_mru_cache_clear_reap_list(mru);
 
-	mutex_spinunlock(&mru->lock, 0);
+	spin_unlock(&mru->lock);
 }
 
 void
@@ -454,13 +458,13 @@
 	elem->key = key;
 	elem->value = value;
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 
 	radix_tree_insert(&mru->store, key, elem);
 	radix_tree_preload_end();
 	_xfs_mru_cache_list_insert(mru, elem);
 
-	mutex_spinunlock(&mru->lock, 0);
+	spin_unlock(&mru->lock);
 
 	return 0;
 }
@@ -483,14 +487,14 @@
 	if (!mru || !mru->lists)
 		return NULL;
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 	elem = radix_tree_delete(&mru->store, key);
 	if (elem) {
 		value = elem->value;
 		list_del(&elem->list_node);
 	}
 
-	mutex_spinunlock(&mru->lock, 0);
+	spin_unlock(&mru->lock);
 
 	if (elem)
 		kmem_zone_free(xfs_mru_elem_zone, elem);
@@ -528,6 +532,10 @@
  *
  * If the element isn't found, this function returns NULL and the spinlock is
  * released.  xfs_mru_cache_done() should NOT be called when this occurs.
+ *
+ * Because sparse isn't smart enough to know about conditional lock return
+ * status, we need to help it get it right by annotating the path that does
+ * not release the lock.
  */
 void *
 xfs_mru_cache_lookup(
@@ -540,14 +548,14 @@
 	if (!mru || !mru->lists)
 		return NULL;
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 	elem = radix_tree_lookup(&mru->store, key);
 	if (elem) {
 		list_del(&elem->list_node);
 		_xfs_mru_cache_list_insert(mru, elem);
-	}
-	else
-		mutex_spinunlock(&mru->lock, 0);
+		__release(mru_lock); /* help sparse not be stupid */
+	} else
+		spin_unlock(&mru->lock);
 
 	return elem ? elem->value : NULL;
 }
@@ -571,10 +579,12 @@
 	if (!mru || !mru->lists)
 		return NULL;
 
-	mutex_spinlock(&mru->lock);
+	spin_lock(&mru->lock);
 	elem = radix_tree_lookup(&mru->store, key);
 	if (!elem)
-		mutex_spinunlock(&mru->lock, 0);
+		spin_unlock(&mru->lock);
+	else
+		__release(mru_lock); /* help sparse not be stupid */
 
 	return elem ? elem->value : NULL;
 }
@@ -586,7 +596,7 @@
  */
 void
 xfs_mru_cache_done(
-	xfs_mru_cache_t	*mru)
+	xfs_mru_cache_t	*mru) __releases(mru->lock)
 {
-	mutex_spinunlock(&mru->lock, 0);
+	spin_unlock(&mru->lock);
 }
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 2ec1d8a..a294e58 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -49,18 +49,17 @@
 {
 	int			error;
 	xfs_trans_t		*tp;
-	unsigned long		s;
 
 	mp->m_qflags = 0;
 	/*
 	 * It is OK to look at sb_qflags here in mount path,
-	 * without SB_LOCK.
+	 * without m_sb_lock.
 	 */
 	if (mp->m_sb.sb_qflags == 0)
 		return 0;
-	s = XFS_SB_LOCK(mp);
+	spin_lock(&mp->m_sb_lock);
 	mp->m_sb.sb_qflags = 0;
-	XFS_SB_UNLOCK(mp, s);
+	spin_unlock(&mp->m_sb_lock);
 
 	/*
 	 * if the fs is readonly, let the incore superblock run
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 44ea0ba..7eb157a 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -39,6 +39,7 @@
 #include "xfs_refcache.h"
 #include "xfs_utils.h"
 #include "xfs_trans_space.h"
+#include "xfs_vnodeops.h"
 
 
 /*
@@ -118,7 +119,7 @@
 	inum1 = ip1->i_ino;
 
 	ASSERT(ip1);
-	ITRACE(ip1);
+	xfs_itrace_ref(ip1);
 
 	/*
 	 * Unlock dp1 and lock dp2 if they are different.
@@ -141,7 +142,7 @@
 		IRELE (ip1);
 		return error;
 	} else {
-		ITRACE(ip2);
+		xfs_itrace_ref(ip2);
 	}
 
 	/*
@@ -247,8 +248,8 @@
 	int		src_namelen = VNAMELEN(src_vname);
 	int		target_namelen = VNAMELEN(target_vname);
 
-	vn_trace_entry(src_dp, "xfs_rename", (inst_t *)__return_address);
-	vn_trace_entry(xfs_vtoi(target_dir_vp), "xfs_rename", (inst_t *)__return_address);
+	xfs_itrace_entry(src_dp);
+	xfs_itrace_entry(xfs_vtoi(target_dir_vp));
 
 	/*
 	 * Find the XFS behavior descriptor for the target directory
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 47082c0..ca83ddf 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -73,18 +73,6 @@
  */
 
 /*
- * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set.
- */
-STATIC int
-xfs_lowbit32(
-	__uint32_t	v)
-{
-	if (v)
-		return ffs(v) - 1;
-	return -1;
-}
-
-/*
  * Allocate space to the bitmap or summary file, and zero it, for growfs.
  */
 STATIC int				/* error */
@@ -444,6 +432,7 @@
 	}
 	bbno = XFS_BITTOBLOCK(mp, bno);
 	i = 0;
+	ASSERT(minlen != 0);
 	log2len = xfs_highbit32(minlen);
 	/*
 	 * Loop over all bitmap blocks (bbno + i is current block).
@@ -612,6 +601,8 @@
 	xfs_suminfo_t	sum;		/* summary information for extents */
 
 	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
+	ASSERT(maxlen != 0);
+
 	/*
 	 * Loop over all the levels starting with maxlen.
 	 * At each level, look at all the bitmap blocks, to see if there
@@ -669,6 +660,9 @@
 		*rtblock = NULLRTBLOCK;
 		return 0;
 	}
+	ASSERT(minlen != 0);
+	ASSERT(maxlen != 0);
+
 	/*
 	 * Loop over sizes, from maxlen down to minlen.
 	 * This time, when we do the allocations, allow smaller ones
@@ -1954,6 +1948,7 @@
 				  nsbp->sb_blocksize * nsbp->sb_rextsize);
 		nsbp->sb_rextents = nsbp->sb_rblocks;
 		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
+		ASSERT(nsbp->sb_rextents != 0);
 		nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
 		nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
 		nrsumsize =
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 799c1f8..8d8dcd2 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -21,8 +21,6 @@
 struct xfs_mount;
 struct xfs_trans;
 
-#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME)
-
 /* Min and max rt extent sizes, specified in bytes */
 #define	XFS_MAX_RTEXTSIZE	(1024 * 1024 * 1024)	/* 1GB */
 #define	XFS_DFL_RTEXTSIZE	(64 * 1024)	        /* 64KB */
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index 49875e1..f87db53 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -32,18 +32,10 @@
 static inline xfs_daddr_t
 xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb)
 {
-	return (((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) ? \
+	return (XFS_IS_REALTIME_INODE(ip) ? \
 		 (xfs_daddr_t)XFS_FSB_TO_BB((ip)->i_mount, (fsb)) : \
 		 XFS_FSB_TO_DADDR((ip)->i_mount, (fsb)));
 }
-#define XFS_FSB_TO_DB_IO(io,fsb) xfs_fsb_to_db_io(io,fsb)
-static inline xfs_daddr_t
-xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb)
-{
-	return (((io)->io_flags & XFS_IOCORE_RT) ? \
-		 XFS_FSB_TO_BB((io)->io_mount, (fsb)) : \
-		 XFS_FSB_TO_DADDR((io)->io_mount, (fsb)));
-}
 
 /*
  * Flags for xfs_free_eofblocks
@@ -61,7 +53,7 @@
 {
 	xfs_extlen_t	extsz;
 
-	if (unlikely(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
+	if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
 		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
 				? ip->i_d.di_extsize
 				: ip->i_mount->m_sb.sb_rextsize;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 8878322..71e4c8d 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1322,7 +1322,6 @@
 	xfs_lsn_t		item_lsn;
 	struct xfs_mount	*mp;
 	int			i;
-	SPLDECL(s);
 
 	lidp = licp->lic_descs;
 	for (i = 0; i < licp->lic_unused; i++, lidp++) {
@@ -1363,7 +1362,7 @@
 		 * the test below.
 		 */
 		mp = lip->li_mountp;
-		AIL_LOCK(mp,s);
+		spin_lock(&mp->m_ail_lock);
 		if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) {
 			/*
 			 * This will set the item's lsn to item_lsn
@@ -1372,9 +1371,9 @@
 			 *
 			 * xfs_trans_update_ail() drops the AIL lock.
 			 */
-			xfs_trans_update_ail(mp, lip, item_lsn, s);
+			xfs_trans_update_ail(mp, lip, item_lsn);
 		} else {
-			AIL_UNLOCK(mp, s);
+			spin_unlock(&mp->m_ail_lock);
 		}
 
 		/*
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 0e26e72..7f40628 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -992,8 +992,9 @@
 				  int *);
 #define xfs_trans_commit(tp, flags)	_xfs_trans_commit(tp, flags, NULL)
 void		xfs_trans_cancel(xfs_trans_t *, int);
-void		xfs_trans_ail_init(struct xfs_mount *);
-xfs_lsn_t	xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t);
+int		xfs_trans_ail_init(struct xfs_mount *);
+void		xfs_trans_ail_destroy(struct xfs_mount *);
+void		xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t);
 xfs_lsn_t	xfs_trans_tail_ail(struct xfs_mount *);
 void		xfs_trans_unlocked_item(struct xfs_mount *,
 					xfs_log_item_t *);
@@ -1001,6 +1002,8 @@
 					xfs_agnumber_t ag,
 					xfs_extlen_t idx);
 
+extern kmem_zone_t	*xfs_trans_zone;
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_TRANS_H__ */
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 5b2ff59..4d6330e 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -34,9 +34,9 @@
 STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_entry_t *, xfs_log_item_t *);
 
 #ifdef DEBUG
-STATIC void xfs_ail_check(xfs_ail_entry_t *);
+STATIC void xfs_ail_check(xfs_ail_entry_t *, xfs_log_item_t *);
 #else
-#define	xfs_ail_check(a)
+#define	xfs_ail_check(a,l)
 #endif /* DEBUG */
 
 
@@ -55,16 +55,15 @@
 {
 	xfs_lsn_t	lsn;
 	xfs_log_item_t	*lip;
-	SPLDECL(s);
 
-	AIL_LOCK(mp,s);
-	lip = xfs_ail_min(&(mp->m_ail));
+	spin_lock(&mp->m_ail_lock);
+	lip = xfs_ail_min(&(mp->m_ail.xa_ail));
 	if (lip == NULL) {
 		lsn = (xfs_lsn_t)0;
 	} else {
 		lsn = lip->li_lsn;
 	}
-	AIL_UNLOCK(mp, s);
+	spin_unlock(&mp->m_ail_lock);
 
 	return lsn;
 }
@@ -72,120 +71,185 @@
 /*
  * xfs_trans_push_ail
  *
- * This routine is called to move the tail of the AIL
- * forward.  It does this by trying to flush items in the AIL
- * whose lsns are below the given threshold_lsn.
+ * This routine is called to move the tail of the AIL forward.  It does this by
+ * trying to flush items in the AIL whose lsns are below the given
+ * threshold_lsn.
  *
- * The routine returns the lsn of the tail of the log.
+ * the push is run asynchronously in a separate thread, so we return the tail
+ * of the log right now instead of the tail after the push. This means we will
+ * either continue right away, or we will sleep waiting on the async thread to
+ * do it's work.
+ *
+ * We do this unlocked - we only need to know whether there is anything in the
+ * AIL at the time we are called. We don't need to access the contents of
+ * any of the objects, so the lock is not needed.
  */
-xfs_lsn_t
+void
 xfs_trans_push_ail(
 	xfs_mount_t		*mp,
 	xfs_lsn_t		threshold_lsn)
 {
-	xfs_lsn_t		lsn;
 	xfs_log_item_t		*lip;
-	int			gen;
-	int			restarts;
-	int			lock_result;
-	int			flush_log;
-	SPLDECL(s);
 
-#define	XFS_TRANS_PUSH_AIL_RESTARTS	1000
+	lip = xfs_ail_min(&mp->m_ail.xa_ail);
+	if (lip && !XFS_FORCED_SHUTDOWN(mp)) {
+		if (XFS_LSN_CMP(threshold_lsn, mp->m_ail.xa_target) > 0)
+			xfsaild_wakeup(mp, threshold_lsn);
+	}
+}
 
-	AIL_LOCK(mp,s);
-	lip = xfs_trans_first_ail(mp, &gen);
-	if (lip == NULL || XFS_FORCED_SHUTDOWN(mp)) {
+/*
+ * Return the item in the AIL with the current lsn.
+ * Return the current tree generation number for use
+ * in calls to xfs_trans_next_ail().
+ */
+STATIC xfs_log_item_t *
+xfs_trans_first_push_ail(
+	xfs_mount_t	*mp,
+	int		*gen,
+	xfs_lsn_t	lsn)
+{
+	xfs_log_item_t	*lip;
+
+	lip = xfs_ail_min(&(mp->m_ail.xa_ail));
+	*gen = (int)mp->m_ail.xa_gen;
+	if (lsn == 0)
+		return lip;
+
+	while (lip && (XFS_LSN_CMP(lip->li_lsn, lsn) < 0))
+		lip = lip->li_ail.ail_forw;
+
+	return lip;
+}
+
+/*
+ * Function that does the work of pushing on the AIL
+ */
+long
+xfsaild_push(
+	xfs_mount_t	*mp,
+	xfs_lsn_t	*last_lsn)
+{
+	long		tout = 1000; /* milliseconds */
+	xfs_lsn_t	last_pushed_lsn = *last_lsn;
+	xfs_lsn_t	target =  mp->m_ail.xa_target;
+	xfs_lsn_t	lsn;
+	xfs_log_item_t	*lip;
+	int		gen;
+	int		restarts;
+	int		flush_log, count, stuck;
+
+#define	XFS_TRANS_PUSH_AIL_RESTARTS	10
+
+	spin_lock(&mp->m_ail_lock);
+	lip = xfs_trans_first_push_ail(mp, &gen, *last_lsn);
+	if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
 		/*
-		 * Just return if the AIL is empty.
+		 * AIL is empty or our push has reached the end.
 		 */
-		AIL_UNLOCK(mp, s);
-		return (xfs_lsn_t)0;
+		spin_unlock(&mp->m_ail_lock);
+		last_pushed_lsn = 0;
+		goto out;
 	}
 
 	XFS_STATS_INC(xs_push_ail);
 
 	/*
 	 * While the item we are looking at is below the given threshold
-	 * try to flush it out.  Make sure to limit the number of times
-	 * we allow xfs_trans_next_ail() to restart scanning from the
-	 * beginning of the list.  We'd like not to stop until we've at least
+	 * try to flush it out. We'd like not to stop until we've at least
 	 * tried to push on everything in the AIL with an LSN less than
-	 * the given threshold. However, we may give up before that if
-	 * we realize that we've been holding the AIL_LOCK for 'too long',
-	 * blocking interrupts. Currently, too long is < 500us roughly.
+	 * the given threshold.
+	 *
+	 * However, we will stop after a certain number of pushes and wait
+	 * for a reduced timeout to fire before pushing further. This
+	 * prevents use from spinning when we can't do anything or there is
+	 * lots of contention on the AIL lists.
 	 */
-	flush_log = 0;
-	restarts = 0;
-	while (((restarts < XFS_TRANS_PUSH_AIL_RESTARTS) &&
-		(XFS_LSN_CMP(lip->li_lsn, threshold_lsn) < 0))) {
+	tout = 10;
+	lsn = lip->li_lsn;
+	flush_log = stuck = count = restarts = 0;
+	while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) {
+		int	lock_result;
 		/*
-		 * If we can lock the item without sleeping, unlock
-		 * the AIL lock and flush the item.  Then re-grab the
-		 * AIL lock so we can look for the next item on the
-		 * AIL.  Since we unlock the AIL while we flush the
-		 * item, the next routine may start over again at the
-		 * the beginning of the list if anything has changed.
-		 * That is what the generation count is for.
+		 * If we can lock the item without sleeping, unlock the AIL
+		 * lock and flush the item.  Then re-grab the AIL lock so we
+		 * can look for the next item on the AIL. List changes are
+		 * handled by the AIL lookup functions internally
 		 *
-		 * If we can't lock the item, either its holder will flush
-		 * it or it is already being flushed or it is being relogged.
-		 * In any of these case it is being taken care of and we
-		 * can just skip to the next item in the list.
+		 * If we can't lock the item, either its holder will flush it
+		 * or it is already being flushed or it is being relogged.  In
+		 * any of these case it is being taken care of and we can just
+		 * skip to the next item in the list.
 		 */
 		lock_result = IOP_TRYLOCK(lip);
+		spin_unlock(&mp->m_ail_lock);
 		switch (lock_result) {
-		      case XFS_ITEM_SUCCESS:
-			AIL_UNLOCK(mp, s);
+		case XFS_ITEM_SUCCESS:
 			XFS_STATS_INC(xs_push_ail_success);
 			IOP_PUSH(lip);
-			AIL_LOCK(mp,s);
+			last_pushed_lsn = lsn;
 			break;
 
-		      case XFS_ITEM_PUSHBUF:
-			AIL_UNLOCK(mp, s);
+		case XFS_ITEM_PUSHBUF:
 			XFS_STATS_INC(xs_push_ail_pushbuf);
-#ifdef XFSRACEDEBUG
-			delay_for_intr();
-			delay(300);
-#endif
-			ASSERT(lip->li_ops->iop_pushbuf);
-			ASSERT(lip);
 			IOP_PUSHBUF(lip);
-			AIL_LOCK(mp,s);
+			last_pushed_lsn = lsn;
 			break;
 
-		      case XFS_ITEM_PINNED:
+		case XFS_ITEM_PINNED:
 			XFS_STATS_INC(xs_push_ail_pinned);
+			stuck++;
 			flush_log = 1;
 			break;
 
-		      case XFS_ITEM_LOCKED:
+		case XFS_ITEM_LOCKED:
 			XFS_STATS_INC(xs_push_ail_locked);
+			last_pushed_lsn = lsn;
+			stuck++;
 			break;
 
-		      case XFS_ITEM_FLUSHING:
+		case XFS_ITEM_FLUSHING:
 			XFS_STATS_INC(xs_push_ail_flushing);
+			last_pushed_lsn = lsn;
+			stuck++;
 			break;
 
-		      default:
+		default:
 			ASSERT(0);
 			break;
 		}
 
-		lip = xfs_trans_next_ail(mp, lip, &gen, &restarts);
-		if (lip == NULL) {
+		spin_lock(&mp->m_ail_lock);
+		/* should we bother continuing? */
+		if (XFS_FORCED_SHUTDOWN(mp))
 			break;
-		}
-		if (XFS_FORCED_SHUTDOWN(mp)) {
-			/*
-			 * Just return if we shut down during the last try.
-			 */
-			AIL_UNLOCK(mp, s);
-			return (xfs_lsn_t)0;
-		}
+		ASSERT(mp->m_log);
 
+		count++;
+
+		/*
+		 * Are there too many items we can't do anything with?
+		 * If we we are skipping too many items because we can't flush
+		 * them or they are already being flushed, we back off and
+		 * given them time to complete whatever operation is being
+		 * done. i.e. remove pressure from the AIL while we can't make
+		 * progress so traversals don't slow down further inserts and
+		 * removals to/from the AIL.
+		 *
+		 * The value of 100 is an arbitrary magic number based on
+		 * observation.
+		 */
+		if (stuck > 100)
+			break;
+
+		lip = xfs_trans_next_ail(mp, lip, &gen, &restarts);
+		if (lip == NULL)
+			break;
+		if (restarts > XFS_TRANS_PUSH_AIL_RESTARTS)
+			break;
+		lsn = lip->li_lsn;
 	}
+	spin_unlock(&mp->m_ail_lock);
 
 	if (flush_log) {
 		/*
@@ -193,22 +257,35 @@
 		 * push out the log so it will become unpinned and
 		 * move forward in the AIL.
 		 */
-		AIL_UNLOCK(mp, s);
 		XFS_STATS_INC(xs_push_ail_flush);
 		xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
-		AIL_LOCK(mp, s);
 	}
 
-	lip = xfs_ail_min(&(mp->m_ail));
-	if (lip == NULL) {
-		lsn = (xfs_lsn_t)0;
-	} else {
-		lsn = lip->li_lsn;
+	/*
+	 * We reached the target so wait a bit longer for I/O to complete and
+	 * remove pushed items from the AIL before we start the next scan from
+	 * the start of the AIL.
+	 */
+	if ((XFS_LSN_CMP(lsn, target) >= 0)) {
+		tout += 20;
+		last_pushed_lsn = 0;
+	} else if ((restarts > XFS_TRANS_PUSH_AIL_RESTARTS) ||
+		   (count && ((stuck * 100) / count > 90))) {
+		/*
+		 * Either there is a lot of contention on the AIL or we
+		 * are stuck due to operations in progress. "Stuck" in this
+		 * case is defined as >90% of the items we tried to push
+		 * were stuck.
+		 *
+		 * Backoff a bit more to allow some I/O to complete before
+		 * continuing from where we were.
+		 */
+		tout += 10;
 	}
-
-	AIL_UNLOCK(mp, s);
-	return lsn;
-}	/* xfs_trans_push_ail */
+out:
+	*last_lsn = last_pushed_lsn;
+	return tout;
+}	/* xfsaild_push */
 
 
 /*
@@ -249,7 +326,7 @@
 	 * the call to xfs_log_move_tail() doesn't do anything if there's
 	 * not enough free space to wake people up so we're safe calling it.
 	 */
-	min_lip = xfs_ail_min(&mp->m_ail);
+	min_lip = xfs_ail_min(&mp->m_ail.xa_ail);
 
 	if (min_lip == lip)
 		xfs_log_move_tail(mp, 1);
@@ -269,21 +346,19 @@
  * has changed.
  *
  * This function must be called with the AIL lock held.  The lock
- * is dropped before returning, so the caller must pass in the
- * cookie returned by AIL_LOCK.
+ * is dropped before returning.
  */
 void
 xfs_trans_update_ail(
 	xfs_mount_t	*mp,
 	xfs_log_item_t	*lip,
-	xfs_lsn_t	lsn,
-	unsigned long	s) __releases(mp->m_ail_lock)
+	xfs_lsn_t	lsn) __releases(mp->m_ail_lock)
 {
 	xfs_ail_entry_t		*ailp;
 	xfs_log_item_t		*dlip=NULL;
 	xfs_log_item_t		*mlip;	/* ptr to minimum lip */
 
-	ailp = &(mp->m_ail);
+	ailp = &(mp->m_ail.xa_ail);
 	mlip = xfs_ail_min(ailp);
 
 	if (lip->li_flags & XFS_LI_IN_AIL) {
@@ -296,14 +371,14 @@
 	lip->li_lsn = lsn;
 
 	xfs_ail_insert(ailp, lip);
-	mp->m_ail_gen++;
+	mp->m_ail.xa_gen++;
 
 	if (mlip == dlip) {
-		mlip = xfs_ail_min(&(mp->m_ail));
-		AIL_UNLOCK(mp, s);
+		mlip = xfs_ail_min(&(mp->m_ail.xa_ail));
+		spin_unlock(&mp->m_ail_lock);
 		xfs_log_move_tail(mp, mlip->li_lsn);
 	} else {
-		AIL_UNLOCK(mp, s);
+		spin_unlock(&mp->m_ail_lock);
 	}
 
 
@@ -322,21 +397,19 @@
  * has changed.
  *
  * This function must be called with the AIL lock held.  The lock
- * is dropped before returning, so the caller must pass in the
- * cookie returned by AIL_LOCK.
+ * is dropped before returning.
  */
 void
 xfs_trans_delete_ail(
 	xfs_mount_t	*mp,
-	xfs_log_item_t	*lip,
-	unsigned long	s) __releases(mp->m_ail_lock)
+	xfs_log_item_t	*lip) __releases(mp->m_ail_lock)
 {
 	xfs_ail_entry_t		*ailp;
 	xfs_log_item_t		*dlip;
 	xfs_log_item_t		*mlip;
 
 	if (lip->li_flags & XFS_LI_IN_AIL) {
-		ailp = &(mp->m_ail);
+		ailp = &(mp->m_ail.xa_ail);
 		mlip = xfs_ail_min(ailp);
 		dlip = xfs_ail_delete(ailp, lip);
 		ASSERT(dlip == lip);
@@ -344,14 +417,14 @@
 
 		lip->li_flags &= ~XFS_LI_IN_AIL;
 		lip->li_lsn = 0;
-		mp->m_ail_gen++;
+		mp->m_ail.xa_gen++;
 
 		if (mlip == dlip) {
-			mlip = xfs_ail_min(&(mp->m_ail));
-			AIL_UNLOCK(mp, s);
+			mlip = xfs_ail_min(&(mp->m_ail.xa_ail));
+			spin_unlock(&mp->m_ail_lock);
 			xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0));
 		} else {
-			AIL_UNLOCK(mp, s);
+			spin_unlock(&mp->m_ail_lock);
 		}
 	}
 	else {
@@ -360,12 +433,12 @@
 		 * serious trouble if we get to this stage.
 		 */
 		if (XFS_FORCED_SHUTDOWN(mp))
-			AIL_UNLOCK(mp, s);
+			spin_unlock(&mp->m_ail_lock);
 		else {
 			xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
 		"%s: attempting to delete a log item that is not in the AIL",
 					__FUNCTION__);
-			AIL_UNLOCK(mp, s);
+			spin_unlock(&mp->m_ail_lock);
 			xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 		}
 	}
@@ -385,10 +458,10 @@
 {
 	xfs_log_item_t	*lip;
 
-	lip = xfs_ail_min(&(mp->m_ail));
-	*gen = (int)mp->m_ail_gen;
+	lip = xfs_ail_min(&(mp->m_ail.xa_ail));
+	*gen = (int)mp->m_ail.xa_gen;
 
-	return (lip);
+	return lip;
 }
 
 /*
@@ -408,11 +481,11 @@
 	xfs_log_item_t	*nlip;
 
 	ASSERT(mp && lip && gen);
-	if (mp->m_ail_gen == *gen) {
-		nlip = xfs_ail_next(&(mp->m_ail), lip);
+	if (mp->m_ail.xa_gen == *gen) {
+		nlip = xfs_ail_next(&(mp->m_ail.xa_ail), lip);
 	} else {
-		nlip = xfs_ail_min(&(mp->m_ail));
-		*gen = (int)mp->m_ail_gen;
+		nlip = xfs_ail_min(&(mp->m_ail).xa_ail);
+		*gen = (int)mp->m_ail.xa_gen;
 		if (restarts != NULL) {
 			XFS_STATS_INC(xs_push_ail_restarts);
 			(*restarts)++;
@@ -437,12 +510,20 @@
 /*
  * Initialize the doubly linked list to point only to itself.
  */
-void
+int
 xfs_trans_ail_init(
 	xfs_mount_t	*mp)
 {
-	mp->m_ail.ail_forw = (xfs_log_item_t*)&(mp->m_ail);
-	mp->m_ail.ail_back = (xfs_log_item_t*)&(mp->m_ail);
+	mp->m_ail.xa_ail.ail_forw = (xfs_log_item_t*)&mp->m_ail.xa_ail;
+	mp->m_ail.xa_ail.ail_back = (xfs_log_item_t*)&mp->m_ail.xa_ail;
+	return xfsaild_start(mp);
+}
+
+void
+xfs_trans_ail_destroy(
+	xfs_mount_t	*mp)
+{
+	xfsaild_stop(mp);
 }
 
 /*
@@ -482,7 +563,7 @@
 	next_lip->li_ail.ail_forw = lip;
 	lip->li_ail.ail_forw->li_ail.ail_back = lip;
 
-	xfs_ail_check(base);
+	xfs_ail_check(base, lip);
 	return;
 }
 
@@ -496,12 +577,12 @@
 	xfs_log_item_t	*lip)
 /* ARGSUSED */
 {
+	xfs_ail_check(base, lip);
 	lip->li_ail.ail_forw->li_ail.ail_back = lip->li_ail.ail_back;
 	lip->li_ail.ail_back->li_ail.ail_forw = lip->li_ail.ail_forw;
 	lip->li_ail.ail_forw = NULL;
 	lip->li_ail.ail_back = NULL;
 
-	xfs_ail_check(base);
 	return lip;
 }
 
@@ -545,13 +626,13 @@
  */
 STATIC void
 xfs_ail_check(
-	xfs_ail_entry_t *base)
+	xfs_ail_entry_t *base,
+	xfs_log_item_t	*lip)
 {
-	xfs_log_item_t	*lip;
 	xfs_log_item_t	*prev_lip;
 
-	lip = base->ail_forw;
-	if (lip == (xfs_log_item_t*)base) {
+	prev_lip = base->ail_forw;
+	if (prev_lip == (xfs_log_item_t*)base) {
 		/*
 		 * Make sure the pointers are correct when the list
 		 * is empty.
@@ -561,9 +642,27 @@
 	}
 
 	/*
+	 * Check the next and previous entries are valid.
+	 */
+	ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+	prev_lip = lip->li_ail.ail_back;
+	if (prev_lip != (xfs_log_item_t*)base) {
+		ASSERT(prev_lip->li_ail.ail_forw == lip);
+		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+	}
+	prev_lip = lip->li_ail.ail_forw;
+	if (prev_lip != (xfs_log_item_t*)base) {
+		ASSERT(prev_lip->li_ail.ail_back == lip);
+		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
+	}
+
+
+#ifdef XFS_TRANS_DEBUG
+	/*
 	 * Walk the list checking forward and backward pointers,
 	 * lsn ordering, and that every entry has the XFS_LI_IN_AIL
-	 * flag set.
+	 * flag set. This is really expensive, so only do it when
+	 * specifically debugging the transaction subsystem.
 	 */
 	prev_lip = (xfs_log_item_t*)base;
 	while (lip != (xfs_log_item_t*)base) {
@@ -578,5 +677,6 @@
 	}
 	ASSERT(lip == (xfs_log_item_t*)base);
 	ASSERT(base->ail_back == prev_lip);
+#endif /* XFS_TRANS_DEBUG */
 }
 #endif /* DEBUG */
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
index 2912aac..66a09f0 100644
--- a/fs/xfs/xfs_trans_item.c
+++ b/fs/xfs/xfs_trans_item.c
@@ -21,6 +21,7 @@
 #include "xfs_log.h"
 #include "xfs_inum.h"
 #include "xfs_trans.h"
+#include "xfs_trans_priv.h"
 
 STATIC int	xfs_trans_unlock_chunk(xfs_log_item_chunk_t *,
 					int, int, xfs_lsn_t);
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 447ac43..3c748c4 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -47,15 +47,22 @@
  * From xfs_trans_ail.c
  */
 void			xfs_trans_update_ail(struct xfs_mount *mp,
-				     struct xfs_log_item *lip, xfs_lsn_t lsn,
-				     unsigned long s)
+				     struct xfs_log_item *lip, xfs_lsn_t lsn)
 				     __releases(mp->m_ail_lock);
 void			xfs_trans_delete_ail(struct xfs_mount *mp,
-				     struct xfs_log_item *lip, unsigned long s)
+				     struct xfs_log_item *lip)
 				     __releases(mp->m_ail_lock);
 struct xfs_log_item	*xfs_trans_first_ail(struct xfs_mount *, int *);
 struct xfs_log_item	*xfs_trans_next_ail(struct xfs_mount *,
 				     struct xfs_log_item *, int *, int *);
 
 
+/*
+ * AIL push thread support
+ */
+long	xfsaild_push(struct xfs_mount *, xfs_lsn_t *);
+void	xfsaild_wakeup(struct xfs_mount *, xfs_lsn_t);
+int	xfsaild_start(struct xfs_mount *);
+void	xfsaild_stop(struct xfs_mount *);
+
 #endif	/* __XFS_TRANS_PRIV_H__ */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 673b405..45d740d 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -73,7 +73,7 @@
 {
 	int		error;
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
 	if (!error) {
@@ -302,6 +302,7 @@
 
 	ASSERT (ip->i_d.di_nlink > 0);
 	ip->i_d.di_nlink--;
+	drop_nlink(ip->i_vnode);
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
 	error = 0;
@@ -330,7 +331,6 @@
 	xfs_inode_t	*ip)
 {
 	xfs_mount_t	*mp;
-	unsigned long		s;
 
 	ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
 	ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1);
@@ -340,13 +340,13 @@
 	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 	mp = tp->t_mountp;
 	if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
-		s = XFS_SB_LOCK(mp);
+		spin_lock(&mp->m_sb_lock);
 		if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
 			XFS_SB_VERSION_ADDNLINK(&mp->m_sb);
-			XFS_SB_UNLOCK(mp, s);
+			spin_unlock(&mp->m_sb_lock);
 			xfs_mod_sb(tp, XFS_SB_VERSIONNUM);
 		} else {
-			XFS_SB_UNLOCK(mp, s);
+			spin_unlock(&mp->m_sb_lock);
 		}
 	}
 	/* Caller must log the inode */
@@ -366,6 +366,7 @@
 
 	ASSERT(ip->i_d.di_nlink > 0);
 	ip->i_d.di_nlink++;
+	inc_nlink(ip->i_vnode);
 	if ((ip->i_d.di_version == XFS_DINODE_VERSION_1) &&
 	    (ip->i_d.di_nlink > XFS_MAXLINK_1)) {
 		/*
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index a00b26d..f857fcc 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -20,8 +20,6 @@
 
 #define IRELE(ip)	VN_RELE(XFS_ITOV(ip))
 #define IHOLD(ip)	VN_HOLD(XFS_ITOV(ip))
-#define	ITRACE(ip)	vn_trace_ref(ip, __FILE__, __LINE__, \
-				(inst_t *)__return_address)
 
 extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
 extern int xfs_dir_lookup_int (xfs_inode_t *, uint, bhv_vname_t *, xfs_ino_t *,
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index a154459..413587f 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -58,17 +58,12 @@
 #include "xfs_vfsops.h"
 
 
-int
+int __init
 xfs_init(void)
 {
-	extern kmem_zone_t	*xfs_bmap_free_item_zone;
-	extern kmem_zone_t	*xfs_btree_cur_zone;
-	extern kmem_zone_t	*xfs_trans_zone;
-	extern kmem_zone_t	*xfs_buf_item_zone;
-	extern kmem_zone_t	*xfs_dabuf_zone;
 #ifdef XFS_DABUF_DEBUG
-	extern lock_t	        xfs_dabuf_global_lock;
-	spinlock_init(&xfs_dabuf_global_lock, "xfsda");
+	extern spinlock_t        xfs_dabuf_global_lock;
+	spin_lock_init(&xfs_dabuf_global_lock);
 #endif
 
 	/*
@@ -152,18 +147,12 @@
 	return 0;
 }
 
-void
+void __exit
 xfs_cleanup(void)
 {
-	extern kmem_zone_t	*xfs_bmap_free_item_zone;
-	extern kmem_zone_t	*xfs_btree_cur_zone;
 	extern kmem_zone_t	*xfs_inode_zone;
-	extern kmem_zone_t	*xfs_trans_zone;
-	extern kmem_zone_t	*xfs_da_state_zone;
-	extern kmem_zone_t	*xfs_dabuf_zone;
 	extern kmem_zone_t	*xfs_efd_zone;
 	extern kmem_zone_t	*xfs_efi_zone;
-	extern kmem_zone_t	*xfs_buf_item_zone;
 	extern kmem_zone_t	*xfs_icluster_zone;
 
 	xfs_cleanup_procfs();
@@ -449,8 +438,6 @@
 	if (error)
 		return error;
 
-	mp->m_io_ops = xfs_iocore_xfs;
-
 	if (args->flags & XFSMNT_QUIET)
 		flags |= XFS_MFSI_QUIET;
 
@@ -544,7 +531,7 @@
 	if ((error = xfs_filestream_mount(mp)))
 		goto error2;
 
-	error = XFS_IOINIT(mp, args, flags);
+	error = xfs_mountfs(mp, flags);
 	if (error)
 		goto error2;
 
@@ -694,7 +681,7 @@
  * care of the metadata. New transactions are already blocked, so we need to
  * wait for any remaining transactions to drain out before proceding.
  */
-STATIC void
+void
 xfs_attr_quiesce(
 	xfs_mount_t	*mp)
 {
@@ -821,80 +808,6 @@
 }
 
 /*
- * xfs_root extracts the root vnode from a vfs.
- *
- * vfsp -- the vfs struct for the desired file system
- * vpp  -- address of the caller's vnode pointer which should be
- *         set to the desired fs root vnode
- */
-int
-xfs_root(
-	xfs_mount_t	*mp,
-	bhv_vnode_t	**vpp)
-{
-	bhv_vnode_t	*vp;
-
-	vp = XFS_ITOV(mp->m_rootip);
-	VN_HOLD(vp);
-	*vpp = vp;
-	return 0;
-}
-
-/*
- * xfs_statvfs
- *
- * Fill in the statvfs structure for the given file system.  We use
- * the superblock lock in the mount structure to ensure a consistent
- * snapshot of the counters returned.
- */
-int
-xfs_statvfs(
-	xfs_mount_t	*mp,
-	bhv_statvfs_t	*statp,
-	bhv_vnode_t	*vp)
-{
-	__uint64_t	fakeinos;
-	xfs_extlen_t	lsize;
-	xfs_sb_t	*sbp;
-	unsigned long	s;
-
-	sbp = &(mp->m_sb);
-
-	statp->f_type = XFS_SB_MAGIC;
-
-	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
-	s = XFS_SB_LOCK(mp);
-	statp->f_bsize = sbp->sb_blocksize;
-	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
-	statp->f_blocks = sbp->sb_dblocks - lsize;
-	statp->f_bfree = statp->f_bavail =
-				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
-	fakeinos = statp->f_bfree << sbp->sb_inopblog;
-#if XFS_BIG_INUMS
-	fakeinos += mp->m_inoadd;
-#endif
-	statp->f_files =
-	    MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
-	if (mp->m_maxicount)
-#if XFS_BIG_INUMS
-		if (!mp->m_inoadd)
-#endif
-			statp->f_files = min_t(typeof(statp->f_files),
-						statp->f_files,
-						mp->m_maxicount);
-	statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
-	XFS_SB_UNLOCK(mp, s);
-
-	xfs_statvfs_fsid(statp, mp);
-	statp->f_namelen = MAXNAMELEN - 1;
-
-	if (vp)
-		XFS_QM_DQSTATVFS(xfs_vtoi(vp), statp);
-	return 0;
-}
-
-
-/*
  * xfs_sync flushes any pending I/O to file system vfsp.
  *
  * This routine is called by vfs_sync() to make sure that things make it
@@ -981,8 +894,6 @@
 	int             *bypassed)
 {
 	xfs_inode_t	*ip = NULL;
-	xfs_inode_t	*ip_next;
-	xfs_buf_t	*bp;
 	bhv_vnode_t	*vp = NULL;
 	int		error;
 	int		last_error;
@@ -992,7 +903,6 @@
 	boolean_t	mount_locked;
 	boolean_t	vnode_refed;
 	int		preempt;
-	xfs_dinode_t	*dip;
 	xfs_iptr_t	*ipointer;
 #ifdef DEBUG
 	boolean_t	ipointer_in = B_FALSE;
@@ -1045,6 +955,8 @@
 
 #define XFS_PREEMPT_MASK	0x7f
 
+	ASSERT(!(flags & SYNC_BDFLUSH));
+
 	if (bypassed)
 		*bypassed = 0;
 	if (mp->m_flags & XFS_MOUNT_RDONLY)
@@ -1057,7 +969,7 @@
 	ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);
 
 	fflag = XFS_B_ASYNC;		/* default is don't wait */
-	if (flags & (SYNC_BDFLUSH | SYNC_DELWRI))
+	if (flags & SYNC_DELWRI)
 		fflag = XFS_B_DELWRI;
 	if (flags & SYNC_WAIT)
 		fflag = 0;		/* synchronous overrides all */
@@ -1147,24 +1059,6 @@
 		}
 
 		/*
-		 * If this is just vfs_sync() or pflushd() calling
-		 * then we can skip inodes for which it looks like
-		 * there is nothing to do.  Since we don't have the
-		 * inode locked this is racy, but these are periodic
-		 * calls so it doesn't matter.  For the others we want
-		 * to know for sure, so we at least try to lock them.
-		 */
-		if (flags & SYNC_BDFLUSH) {
-			if (((ip->i_itemp == NULL) ||
-			     !(ip->i_itemp->ili_format.ilf_fields &
-			       XFS_ILOG_ALL)) &&
-			    (ip->i_update_core == 0)) {
-				ip = ip->i_mnext;
-				continue;
-			}
-		}
-
-		/*
 		 * Try to lock without sleeping.  We're out of order with
 		 * the inode list lock here, so if we fail we need to drop
 		 * the mount lock and try again.  If we're called from
@@ -1181,7 +1075,7 @@
 		 * it.
 		 */
 		if (xfs_ilock_nowait(ip, lock_flags) == 0) {
-			if ((flags & SYNC_BDFLUSH) || (vp == NULL)) {
+			if (vp == NULL) {
 				ip = ip->i_mnext;
 				continue;
 			}
@@ -1242,160 +1136,27 @@
 			xfs_ilock(ip, XFS_ILOCK_SHARED);
 		}
 
-		if (flags & SYNC_BDFLUSH) {
-			if ((flags & SYNC_ATTR) &&
-			    ((ip->i_update_core) ||
-			     ((ip->i_itemp != NULL) &&
-			      (ip->i_itemp->ili_format.ilf_fields != 0)))) {
+		if ((flags & SYNC_ATTR) &&
+		    (ip->i_update_core ||
+		     (ip->i_itemp && ip->i_itemp->ili_format.ilf_fields))) {
+			if (mount_locked)
+				IPOINTER_INSERT(ip, mp);
 
-				/* Insert marker and drop lock if not already
-				 * done.
-				 */
-				if (mount_locked) {
-					IPOINTER_INSERT(ip, mp);
-				}
+			if (flags & SYNC_WAIT) {
+				xfs_iflock(ip);
+				error = xfs_iflush(ip, XFS_IFLUSH_SYNC);
 
-				/*
-				 * We don't want the periodic flushing of the
-				 * inodes by vfs_sync() to interfere with
-				 * I/O to the file, especially read I/O
-				 * where it is only the access time stamp
-				 * that is being flushed out.  To prevent
-				 * long periods where we have both inode
-				 * locks held shared here while reading the
-				 * inode's buffer in from disk, we drop the
-				 * inode lock while reading in the inode
-				 * buffer.  We have to release the buffer
-				 * and reacquire the inode lock so that they
-				 * are acquired in the proper order (inode
-				 * locks first).  The buffer will go at the
-				 * end of the lru chain, though, so we can
-				 * expect it to still be there when we go
-				 * for it again in xfs_iflush().
-				 */
-				if ((xfs_ipincount(ip) == 0) &&
-				    xfs_iflock_nowait(ip)) {
-
-					xfs_ifunlock(ip);
-					xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
-					error = xfs_itobp(mp, NULL, ip,
-							  &dip, &bp, 0, 0);
-					if (!error) {
-						xfs_buf_relse(bp);
-					} else {
-						/* Bailing out, remove the
-						 * marker and free it.
-						 */
-						XFS_MOUNT_ILOCK(mp);
-						IPOINTER_REMOVE(ip, mp);
-						XFS_MOUNT_IUNLOCK(mp);
-
-						ASSERT(!(lock_flags &
-							XFS_IOLOCK_SHARED));
-
-						kmem_free(ipointer,
-							sizeof(xfs_iptr_t));
-						return (0);
-					}
-
-					/*
-					 * Since we dropped the inode lock,
-					 * the inode may have been reclaimed.
-					 * Therefore, we reacquire the mount
-					 * lock and check to see if we were the
-					 * inode reclaimed. If this happened
-					 * then the ipointer marker will no
-					 * longer point back at us. In this
-					 * case, move ip along to the inode
-					 * after the marker, remove the marker
-					 * and continue.
-					 */
-					XFS_MOUNT_ILOCK(mp);
-					mount_locked = B_TRUE;
-
-					if (ip != ipointer->ip_mprev) {
-						IPOINTER_REMOVE(ip, mp);
-
-						ASSERT(!vnode_refed);
-						ASSERT(!(lock_flags &
-							XFS_IOLOCK_SHARED));
-						continue;
-					}
-
-					ASSERT(ip->i_mount == mp);
-
-					if (xfs_ilock_nowait(ip,
-						    XFS_ILOCK_SHARED) == 0) {
-						ASSERT(ip->i_mount == mp);
-						/*
-						 * We failed to reacquire
-						 * the inode lock without
-						 * sleeping, so just skip
-						 * the inode for now.  We
-						 * clear the ILOCK bit from
-						 * the lock_flags so that we
-						 * won't try to drop a lock
-						 * we don't hold below.
-						 */
-						lock_flags &= ~XFS_ILOCK_SHARED;
-						IPOINTER_REMOVE(ip_next, mp);
-					} else if ((xfs_ipincount(ip) == 0) &&
-						   xfs_iflock_nowait(ip)) {
-						ASSERT(ip->i_mount == mp);
-						/*
-						 * Since this is vfs_sync()
-						 * calling we only flush the
-						 * inode out if we can lock
-						 * it without sleeping and
-						 * it is not pinned.  Drop
-						 * the mount lock here so
-						 * that we don't hold it for
-						 * too long. We already have
-						 * a marker in the list here.
-						 */
-						XFS_MOUNT_IUNLOCK(mp);
-						mount_locked = B_FALSE;
-						error = xfs_iflush(ip,
-							   XFS_IFLUSH_DELWRI);
-					} else {
-						ASSERT(ip->i_mount == mp);
-						IPOINTER_REMOVE(ip_next, mp);
-					}
-				}
-
-			}
-
-		} else {
-			if ((flags & SYNC_ATTR) &&
-			    ((ip->i_update_core) ||
-			     ((ip->i_itemp != NULL) &&
-			      (ip->i_itemp->ili_format.ilf_fields != 0)))) {
-				if (mount_locked) {
-					IPOINTER_INSERT(ip, mp);
-				}
-
-				if (flags & SYNC_WAIT) {
-					xfs_iflock(ip);
-					error = xfs_iflush(ip,
-							   XFS_IFLUSH_SYNC);
-				} else {
-					/*
-					 * If we can't acquire the flush
-					 * lock, then the inode is already
-					 * being flushed so don't bother
-					 * waiting.  If we can lock it then
-					 * do a delwri flush so we can
-					 * combine multiple inode flushes
-					 * in each disk write.
-					 */
-					if (xfs_iflock_nowait(ip)) {
-						error = xfs_iflush(ip,
-							   XFS_IFLUSH_DELWRI);
-					}
-					else if (bypassed)
-						(*bypassed)++;
-				}
+			/*
+			 * If we can't acquire the flush lock, then the inode
+			 * is already being flushed so don't bother waiting.
+			 *
+			 * If we can lock it then do a delwri flush so we can
+			 * combine multiple inode flushes in each disk write.
+			 */
+			} else if (xfs_iflock_nowait(ip)) {
+				error = xfs_iflush(ip, XFS_IFLUSH_DELWRI);
+			} else if (bypassed) {
+				(*bypassed)++;
 			}
 		}
 
@@ -1627,499 +1388,3 @@
 
 	return XFS_ERROR(last_error);
 }
-
-/*
- * xfs_vget - called by DMAPI and NFSD to get vnode from file handle
- */
-int
-xfs_vget(
-	xfs_mount_t	*mp,
-	bhv_vnode_t	**vpp,
-	xfs_fid_t	*xfid)
-{
-	xfs_inode_t	*ip;
-	int		error;
-	xfs_ino_t	ino;
-	unsigned int	igen;
-
-	/*
-	 * Invalid.  Since handles can be created in user space and passed in
-	 * via gethandle(), this is not cause for a panic.
-	 */
-	if (xfid->fid_len != sizeof(*xfid) - sizeof(xfid->fid_len))
-		return XFS_ERROR(EINVAL);
-
-	ino  = xfid->fid_ino;
-	igen = xfid->fid_gen;
-
-	/*
-	 * NFS can sometimes send requests for ino 0.  Fail them gracefully.
-	 */
-	if (ino == 0)
-		return XFS_ERROR(ESTALE);
-
-	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
-	if (error) {
-		*vpp = NULL;
-		return error;
-	}
-
-	if (ip == NULL) {
-		*vpp = NULL;
-		return XFS_ERROR(EIO);
-	}
-
-	if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
-		xfs_iput_new(ip, XFS_ILOCK_SHARED);
-		*vpp = NULL;
-		return XFS_ERROR(ENOENT);
-	}
-
-	*vpp = XFS_ITOV(ip);
-	xfs_iunlock(ip, XFS_ILOCK_SHARED);
-	return 0;
-}
-
-
-#define MNTOPT_LOGBUFS	"logbufs"	/* number of XFS log buffers */
-#define MNTOPT_LOGBSIZE	"logbsize"	/* size of XFS log buffers */
-#define MNTOPT_LOGDEV	"logdev"	/* log device */
-#define MNTOPT_RTDEV	"rtdev"		/* realtime I/O device */
-#define MNTOPT_BIOSIZE	"biosize"	/* log2 of preferred buffered io size */
-#define MNTOPT_WSYNC	"wsync"		/* safe-mode nfs compatible mount */
-#define MNTOPT_INO64	"ino64"		/* force inodes into 64-bit range */
-#define MNTOPT_NOALIGN	"noalign"	/* turn off stripe alignment */
-#define MNTOPT_SWALLOC	"swalloc"	/* turn on stripe width allocation */
-#define MNTOPT_SUNIT	"sunit"		/* data volume stripe unit */
-#define MNTOPT_SWIDTH	"swidth"	/* data volume stripe width */
-#define MNTOPT_NOUUID	"nouuid"	/* ignore filesystem UUID */
-#define MNTOPT_MTPT	"mtpt"		/* filesystem mount point */
-#define MNTOPT_GRPID	"grpid"		/* group-ID from parent directory */
-#define MNTOPT_NOGRPID	"nogrpid"	/* group-ID from current process */
-#define MNTOPT_BSDGROUPS    "bsdgroups"    /* group-ID from parent directory */
-#define MNTOPT_SYSVGROUPS   "sysvgroups"   /* group-ID from current process */
-#define MNTOPT_ALLOCSIZE    "allocsize"    /* preferred allocation size */
-#define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */
-#define MNTOPT_BARRIER	"barrier"	/* use writer barriers for log write and
-					 * unwritten extent conversion */
-#define MNTOPT_NOBARRIER "nobarrier"	/* .. disable */
-#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
-#define MNTOPT_64BITINODE   "inode64"	/* inodes can be allocated anywhere */
-#define MNTOPT_IKEEP	"ikeep"		/* do not free empty inode clusters */
-#define MNTOPT_NOIKEEP	"noikeep"	/* free empty inode clusters */
-#define MNTOPT_LARGEIO	   "largeio"	/* report large I/O sizes in stat() */
-#define MNTOPT_NOLARGEIO   "nolargeio"	/* do not report large I/O sizes
-					 * in stat(). */
-#define MNTOPT_ATTR2	"attr2"		/* do use attr2 attribute format */
-#define MNTOPT_NOATTR2	"noattr2"	/* do not use attr2 attribute format */
-#define MNTOPT_FILESTREAM  "filestreams" /* use filestreams allocator */
-#define MNTOPT_QUOTA	"quota"		/* disk quotas (user) */
-#define MNTOPT_NOQUOTA	"noquota"	/* no quotas */
-#define MNTOPT_USRQUOTA	"usrquota"	/* user quota enabled */
-#define MNTOPT_GRPQUOTA	"grpquota"	/* group quota enabled */
-#define MNTOPT_PRJQUOTA	"prjquota"	/* project quota enabled */
-#define MNTOPT_UQUOTA	"uquota"	/* user quota (IRIX variant) */
-#define MNTOPT_GQUOTA	"gquota"	/* group quota (IRIX variant) */
-#define MNTOPT_PQUOTA	"pquota"	/* project quota (IRIX variant) */
-#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
-#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
-#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
-#define MNTOPT_QUOTANOENF  "qnoenforce"	/* same as uqnoenforce */
-#define MNTOPT_DMAPI	"dmapi"		/* DMI enabled (DMAPI / XDSM) */
-#define MNTOPT_XDSM	"xdsm"		/* DMI enabled (DMAPI / XDSM) */
-#define MNTOPT_DMI	"dmi"		/* DMI enabled (DMAPI / XDSM) */
-
-STATIC unsigned long
-suffix_strtoul(char *s, char **endp, unsigned int base)
-{
-	int	last, shift_left_factor = 0;
-	char	*value = s;
-
-	last = strlen(value) - 1;
-	if (value[last] == 'K' || value[last] == 'k') {
-		shift_left_factor = 10;
-		value[last] = '\0';
-	}
-	if (value[last] == 'M' || value[last] == 'm') {
-		shift_left_factor = 20;
-		value[last] = '\0';
-	}
-	if (value[last] == 'G' || value[last] == 'g') {
-		shift_left_factor = 30;
-		value[last] = '\0';
-	}
-
-	return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
-}
-
-int
-xfs_parseargs(
-	struct xfs_mount	*mp,
-	char			*options,
-	struct xfs_mount_args	*args,
-	int			update)
-{
-	char			*this_char, *value, *eov;
-	int			dsunit, dswidth, vol_dsunit, vol_dswidth;
-	int			iosize;
-	int			ikeep = 0;
-
-	args->flags |= XFSMNT_BARRIER;
-	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
-
-	if (!options)
-		goto done;
-
-	iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
-
-	while ((this_char = strsep(&options, ",")) != NULL) {
-		if (!*this_char)
-			continue;
-		if ((value = strchr(this_char, '=')) != NULL)
-			*value++ = 0;
-
-		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			args->logbufs = simple_strtoul(value, &eov, 10);
-		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			args->logbufsize = suffix_strtoul(value, &eov, 10);
-		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			strncpy(args->logname, value, MAXNAMELEN);
-		} else if (!strcmp(this_char, MNTOPT_MTPT)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			strncpy(args->mtpt, value, MAXNAMELEN);
-		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			strncpy(args->rtname, value, MAXNAMELEN);
-		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			iosize = simple_strtoul(value, &eov, 10);
-			args->flags |= XFSMNT_IOSIZE;
-			args->iosizelog = (uint8_t) iosize;
-		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			iosize = suffix_strtoul(value, &eov, 10);
-			args->flags |= XFSMNT_IOSIZE;
-			args->iosizelog = ffs(iosize) - 1;
-		} else if (!strcmp(this_char, MNTOPT_GRPID) ||
-			   !strcmp(this_char, MNTOPT_BSDGROUPS)) {
-			mp->m_flags |= XFS_MOUNT_GRPID;
-		} else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
-			   !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
-			mp->m_flags &= ~XFS_MOUNT_GRPID;
-		} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
-			args->flags |= XFSMNT_WSYNC;
-		} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
-			args->flags |= XFSMNT_OSYNCISOSYNC;
-		} else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
-			args->flags |= XFSMNT_NORECOVERY;
-		} else if (!strcmp(this_char, MNTOPT_INO64)) {
-			args->flags |= XFSMNT_INO64;
-#if !XFS_BIG_INUMS
-			cmn_err(CE_WARN,
-				"XFS: %s option not allowed on this system",
-				this_char);
-			return EINVAL;
-#endif
-		} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
-			args->flags |= XFSMNT_NOALIGN;
-		} else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
-			args->flags |= XFSMNT_SWALLOC;
-		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			dsunit = simple_strtoul(value, &eov, 10);
-		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
-			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
-					this_char);
-				return EINVAL;
-			}
-			dswidth = simple_strtoul(value, &eov, 10);
-		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
-			args->flags &= ~XFSMNT_32BITINODES;
-#if !XFS_BIG_INUMS
-			cmn_err(CE_WARN,
-				"XFS: %s option not allowed on this system",
-				this_char);
-			return EINVAL;
-#endif
-		} else if (!strcmp(this_char, MNTOPT_NOUUID)) {
-			args->flags |= XFSMNT_NOUUID;
-		} else if (!strcmp(this_char, MNTOPT_BARRIER)) {
-			args->flags |= XFSMNT_BARRIER;
-		} else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
-			args->flags &= ~XFSMNT_BARRIER;
-		} else if (!strcmp(this_char, MNTOPT_IKEEP)) {
-			ikeep = 1;
-			args->flags &= ~XFSMNT_IDELETE;
-		} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
-			args->flags |= XFSMNT_IDELETE;
-		} else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
-			args->flags2 &= ~XFSMNT2_COMPAT_IOSIZE;
-		} else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
-			args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
-		} else if (!strcmp(this_char, MNTOPT_ATTR2)) {
-			args->flags |= XFSMNT_ATTR2;
-		} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
-			args->flags &= ~XFSMNT_ATTR2;
-		} else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
-			args->flags2 |= XFSMNT2_FILESTREAMS;
-		} else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
-			args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
-			args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
-		} else if (!strcmp(this_char, MNTOPT_QUOTA) ||
-			   !strcmp(this_char, MNTOPT_UQUOTA) ||
-			   !strcmp(this_char, MNTOPT_USRQUOTA)) {
-			args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
-		} else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
-			   !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
-			args->flags |= XFSMNT_UQUOTA;
-			args->flags &= ~XFSMNT_UQUOTAENF;
-		} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
-			   !strcmp(this_char, MNTOPT_PRJQUOTA)) {
-			args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
-		} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
-			args->flags |= XFSMNT_PQUOTA;
-			args->flags &= ~XFSMNT_PQUOTAENF;
-		} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
-			   !strcmp(this_char, MNTOPT_GRPQUOTA)) {
-			args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
-		} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
-			args->flags |= XFSMNT_GQUOTA;
-			args->flags &= ~XFSMNT_GQUOTAENF;
-		} else if (!strcmp(this_char, MNTOPT_DMAPI)) {
-			args->flags |= XFSMNT_DMAPI;
-		} else if (!strcmp(this_char, MNTOPT_XDSM)) {
-			args->flags |= XFSMNT_DMAPI;
-		} else if (!strcmp(this_char, MNTOPT_DMI)) {
-			args->flags |= XFSMNT_DMAPI;
-		} else if (!strcmp(this_char, "ihashsize")) {
-			cmn_err(CE_WARN,
-	"XFS: ihashsize no longer used, option is deprecated.");
-		} else if (!strcmp(this_char, "osyncisdsync")) {
-			/* no-op, this is now the default */
-			cmn_err(CE_WARN,
-	"XFS: osyncisdsync is now the default, option is deprecated.");
-		} else if (!strcmp(this_char, "irixsgid")) {
-			cmn_err(CE_WARN,
-	"XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
-		} else {
-			cmn_err(CE_WARN,
-				"XFS: unknown mount option [%s].", this_char);
-			return EINVAL;
-		}
-	}
-
-	if (args->flags & XFSMNT_NORECOVERY) {
-		if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) {
-			cmn_err(CE_WARN,
-				"XFS: no-recovery mounts must be read-only.");
-			return EINVAL;
-		}
-	}
-
-	if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
-		cmn_err(CE_WARN,
-	"XFS: sunit and swidth options incompatible with the noalign option");
-		return EINVAL;
-	}
-
-	if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
-		cmn_err(CE_WARN,
-			"XFS: cannot mount with both project and group quota");
-		return EINVAL;
-	}
-
-	if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
-		printk("XFS: %s option needs the mount point option as well\n",
-			MNTOPT_DMAPI);
-		return EINVAL;
-	}
-
-	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
-		cmn_err(CE_WARN,
-			"XFS: sunit and swidth must be specified together");
-		return EINVAL;
-	}
-
-	if (dsunit && (dswidth % dsunit != 0)) {
-		cmn_err(CE_WARN,
-	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
-			dswidth, dsunit);
-		return EINVAL;
-	}
-
-	/*
-	 * Applications using DMI filesystems often expect the
-	 * inode generation number to be monotonically increasing.
-	 * If we delete inode chunks we break this assumption, so
-	 * keep unused inode chunks on disk for DMI filesystems
-	 * until we come up with a better solution.
-	 * Note that if "ikeep" or "noikeep" mount options are
-	 * supplied, then they are honored.
-	 */
-	if (!(args->flags & XFSMNT_DMAPI) && !ikeep)
-		args->flags |= XFSMNT_IDELETE;
-
-	if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
-		if (dsunit) {
-			args->sunit = dsunit;
-			args->flags |= XFSMNT_RETERR;
-		} else {
-			args->sunit = vol_dsunit;
-		}
-		dswidth ? (args->swidth = dswidth) :
-			  (args->swidth = vol_dswidth);
-	} else {
-		args->sunit = args->swidth = 0;
-	}
-
-done:
-	if (args->flags & XFSMNT_32BITINODES)
-		mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
-	if (args->flags2)
-		args->flags |= XFSMNT_FLAGS2;
-	return 0;
-}
-
-int
-xfs_showargs(
-	struct xfs_mount	*mp,
-	struct seq_file		*m)
-{
-	static struct proc_xfs_info {
-		int	flag;
-		char	*str;
-	} xfs_info[] = {
-		/* the few simple ones we can get from the mount struct */
-		{ XFS_MOUNT_WSYNC,		"," MNTOPT_WSYNC },
-		{ XFS_MOUNT_INO64,		"," MNTOPT_INO64 },
-		{ XFS_MOUNT_NOALIGN,		"," MNTOPT_NOALIGN },
-		{ XFS_MOUNT_SWALLOC,		"," MNTOPT_SWALLOC },
-		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID },
-		{ XFS_MOUNT_NORECOVERY,		"," MNTOPT_NORECOVERY },
-		{ XFS_MOUNT_OSYNCISOSYNC,	"," MNTOPT_OSYNCISOSYNC },
-		{ 0, NULL }
-	};
-	struct proc_xfs_info	*xfs_infop;
-
-	for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
-		if (mp->m_flags & xfs_infop->flag)
-			seq_puts(m, xfs_infop->str);
-	}
-
-	if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
-		seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
-				(int)(1 << mp->m_writeio_log) >> 10);
-
-	if (mp->m_logbufs > 0)
-		seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
-	if (mp->m_logbsize > 0)
-		seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
-
-	if (mp->m_logname)
-		seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
-	if (mp->m_rtname)
-		seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
-
-	if (mp->m_dalign > 0)
-		seq_printf(m, "," MNTOPT_SUNIT "=%d",
-				(int)XFS_FSB_TO_BB(mp, mp->m_dalign));
-	if (mp->m_swidth > 0)
-		seq_printf(m, "," MNTOPT_SWIDTH "=%d",
-				(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
-
-	if (!(mp->m_flags & XFS_MOUNT_IDELETE))
-		seq_printf(m, "," MNTOPT_IKEEP);
-	if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
-		seq_printf(m, "," MNTOPT_LARGEIO);
-
-	if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS))
-		seq_printf(m, "," MNTOPT_64BITINODE);
-	if (mp->m_flags & XFS_MOUNT_GRPID)
-		seq_printf(m, "," MNTOPT_GRPID);
-
-	if (mp->m_qflags & XFS_UQUOTA_ACCT) {
-		if (mp->m_qflags & XFS_UQUOTA_ENFD)
-			seq_puts(m, "," MNTOPT_USRQUOTA);
-		else
-			seq_puts(m, "," MNTOPT_UQUOTANOENF);
-	}
-
-	if (mp->m_qflags & XFS_PQUOTA_ACCT) {
-		if (mp->m_qflags & XFS_OQUOTA_ENFD)
-			seq_puts(m, "," MNTOPT_PRJQUOTA);
-		else
-			seq_puts(m, "," MNTOPT_PQUOTANOENF);
-	}
-
-	if (mp->m_qflags & XFS_GQUOTA_ACCT) {
-		if (mp->m_qflags & XFS_OQUOTA_ENFD)
-			seq_puts(m, "," MNTOPT_GRPQUOTA);
-		else
-			seq_puts(m, "," MNTOPT_GQUOTANOENF);
-	}
-
-	if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
-		seq_puts(m, "," MNTOPT_NOQUOTA);
-
-	if (mp->m_flags & XFS_MOUNT_DMAPI)
-		seq_puts(m, "," MNTOPT_DMAPI);
-	return 0;
-}
-
-/*
- * Second stage of a freeze. The data is already frozen so we only
- * need to take care of themetadata. Once that's done write a dummy
- * record to dirty the log in case of a crash while frozen.
- */
-void
-xfs_freeze(
-	xfs_mount_t	*mp)
-{
-	xfs_attr_quiesce(mp);
-	xfs_fs_log_dummy(mp);
-}
diff --git a/fs/xfs/xfs_vfsops.h b/fs/xfs/xfs_vfsops.h
index a592fe0..1688817 100644
--- a/fs/xfs/xfs_vfsops.h
+++ b/fs/xfs/xfs_vfsops.h
@@ -13,16 +13,9 @@
 int xfs_unmount(struct xfs_mount *mp, int flags, struct cred *credp);
 int xfs_mntupdate(struct xfs_mount *mp, int *flags,
 		struct xfs_mount_args *args);
-int xfs_root(struct xfs_mount *mp, bhv_vnode_t **vpp);
-int xfs_statvfs(struct xfs_mount *mp, struct kstatfs *statp,
-		bhv_vnode_t *vp);
 int xfs_sync(struct xfs_mount *mp, int flags);
-int xfs_vget(struct xfs_mount *mp, bhv_vnode_t **vpp, struct xfs_fid *xfid);
-int xfs_parseargs(struct xfs_mount *mp, char *options,
-		struct xfs_mount_args *args, int update);
-int xfs_showargs(struct xfs_mount *mp, struct seq_file *m);
-void xfs_freeze(struct xfs_mount *mp);
 void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
 		int lnnum);
+void xfs_attr_quiesce(struct xfs_mount *mp);
 
 #endif /* _XFS_VFSOPS_H */
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index efd5aff..5130524 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -88,7 +88,7 @@
 	bhv_vnode_t	*vp = XFS_ITOV(ip);
 	xfs_mount_t	*mp = ip->i_mount;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -136,7 +136,7 @@
 	default:
 		vap->va_rdev = 0;
 
-		if (!(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
+		if (!(XFS_IS_REALTIME_INODE(ip))) {
 			vap->va_blocksize = xfs_preferred_iosize(mp);
 		} else {
 
@@ -228,7 +228,7 @@
 	int			file_owner;
 	int			need_iolock = 1;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	if (mp->m_flags & XFS_MOUNT_RDONLY)
 		return XFS_ERROR(EROFS);
@@ -508,7 +508,7 @@
 		 */
 		if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
 		    (mask & XFS_AT_XFLAGS) &&
-		    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) !=
+		    (XFS_IS_REALTIME_INODE(ip)) !=
 		    (vap->va_xflags & XFS_XFLAG_REALTIME)) {
 			code = XFS_ERROR(EINVAL);	/* EFBIG? */
 			goto error_return;
@@ -520,7 +520,7 @@
 		if ((mask & XFS_AT_EXTSIZE) && vap->va_extsize != 0) {
 			xfs_extlen_t	size;
 
-			if ((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ||
+			if (XFS_IS_REALTIME_INODE(ip) ||
 			    ((mask & XFS_AT_XFLAGS) &&
 			    (vap->va_xflags & XFS_XFLAG_REALTIME))) {
 				size = mp->m_sb.sb_rextsize <<
@@ -804,12 +804,8 @@
 				if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
 					di_flags |= XFS_DIFLAG_EXTSZINHERIT;
 			} else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
-				if (vap->va_xflags & XFS_XFLAG_REALTIME) {
+				if (vap->va_xflags & XFS_XFLAG_REALTIME)
 					di_flags |= XFS_DIFLAG_REALTIME;
-					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
-				} else {
-					ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
-				}
 				if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
 					di_flags |= XFS_DIFLAG_EXTSIZE;
 			}
@@ -902,28 +898,6 @@
 	return code;
 }
 
-
-/*
- * xfs_access
- * Null conversion from vnode mode bits to inode mode bits, as in efs.
- */
-int
-xfs_access(
-	xfs_inode_t	*ip,
-	int		mode,
-	cred_t		*credp)
-{
-	int		error;
-
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
-
-	xfs_ilock(ip, XFS_ILOCK_SHARED);
-	error = xfs_iaccess(ip, mode, credp);
-	xfs_iunlock(ip, XFS_ILOCK_SHARED);
-	return error;
-}
-
-
 /*
  * The maximum pathlen is 1024 bytes. Since the minimum file system
  * blocksize is 512 bytes, we can get a max of 2 extents back from
@@ -987,7 +961,7 @@
 	int		pathlen;
 	int		error = 0;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -1033,7 +1007,7 @@
 	int		error;
 	int		log_flushed = 0, changed = 1;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	ASSERT(start >= 0 && stop >= -1);
 
@@ -1149,7 +1123,7 @@
 		 * If this inode is on the RT dev we need to flush that
 		 * cache as well.
 		 */
-		if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
+		if (XFS_IS_REALTIME_INODE(ip))
 			xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
 	}
 
@@ -1188,7 +1162,7 @@
 
 	nimaps = 1;
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
-	error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0,
+	error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0,
 			  NULL, 0, &imap, &nimaps, NULL, NULL);
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
@@ -1562,9 +1536,6 @@
 			error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
 			if (error)
 				return error;
-			/* Update linux inode block count after free above */
-			vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
-				ip->i_d.di_nblocks + ip->i_delayed_blks);
 		}
 	}
 
@@ -1592,7 +1563,7 @@
 	int		error;
 	int		truncate;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	/*
 	 * If the inode is already free, then there can be nothing
@@ -1638,9 +1609,6 @@
 			error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
 			if (error)
 				return VN_INACTIVE_CACHE;
-			/* Update linux inode block count after free above */
-			vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
-				ip->i_d.di_nblocks + ip->i_delayed_blks);
 		}
 		goto out;
 	}
@@ -1805,7 +1773,7 @@
 	int			error;
 	uint			lock_mode;
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 		return XFS_ERROR(EIO);
@@ -1814,7 +1782,7 @@
 	error = xfs_dir_lookup_int(dp, lock_mode, dentry, &e_inum, &ip);
 	if (!error) {
 		*vpp = XFS_ITOV(ip);
-		ITRACE(ip);
+		xfs_itrace_ref(ip);
 	}
 	xfs_iunlock_map_shared(dp, lock_mode);
 	return error;
@@ -1848,7 +1816,7 @@
 	int			namelen;
 
 	ASSERT(!*vpp);
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	namelen = VNAMELEN(dentry);
 
@@ -1930,7 +1898,7 @@
 			goto error_return;
 		goto abort_return;
 	}
-	ITRACE(ip);
+	xfs_itrace_ref(ip);
 
 	/*
 	 * At this point, we've gotten a newly allocated inode.
@@ -2098,7 +2066,7 @@
 
 	e_inum = ip->i_ino;
 
-	ITRACE(ip);
+	xfs_itrace_ref(ip);
 
 	/*
 	 * We want to lock in increasing inum. Since we've already
@@ -2321,7 +2289,7 @@
 	uint			resblks;
 	int			namelen;
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -2364,9 +2332,8 @@
 
 	dm_di_mode = ip->i_d.di_mode;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
-
-	ITRACE(ip);
+	xfs_itrace_entry(ip);
+	xfs_itrace_ref(ip);
 
 	error = XFS_QM_DQATTACH(mp, dp, 0);
 	if (!error && dp != ip)
@@ -2498,8 +2465,7 @@
 	if (link_zero && xfs_inode_is_filestream(ip))
 		xfs_filestream_deassociate(ip);
 
-	vn_trace_exit(ip, __FUNCTION__, (inst_t *)__return_address);
-
+	xfs_itrace_exit(ip);
 	IRELE(ip);
 
 /*	Fall through to std_return with error = 0 */
@@ -2562,8 +2528,8 @@
 	char			*target_name = VNAME(dentry);
 	int			target_namelen;
 
-	vn_trace_entry(tdp, __FUNCTION__, (inst_t *)__return_address);
-	vn_trace_entry(xfs_vtoi(src_vp), __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(tdp);
+	xfs_itrace_entry(xfs_vtoi(src_vp));
 
 	target_namelen = VNAMELEN(dentry);
 	ASSERT(!VN_ISDIR(src_vp));
@@ -2744,7 +2710,7 @@
 
 	/* Return through std_return after this point. */
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	mp = dp->i_mount;
 	udqp = gdqp = NULL;
@@ -2810,7 +2776,7 @@
 			goto error_return;
 		goto abort_return;
 	}
-	ITRACE(cdp);
+	xfs_itrace_ref(cdp);
 
 	/*
 	 * Now we add the directory inode to the transaction.
@@ -2936,7 +2902,7 @@
 	int			last_cdp_link;
 	uint			resblks;
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(dp);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -3041,7 +3007,7 @@
 		VN_HOLD(dir_vp);
 	}
 
-	ITRACE(cdp);
+	xfs_itrace_ref(cdp);
 	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
 
 	ASSERT(cdp->i_d.di_nlink >= 2);
@@ -3189,8 +3155,7 @@
 	ip = NULL;
 	tp = NULL;
 
-	vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
-
+	xfs_itrace_entry(dp);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -3317,7 +3282,7 @@
 			goto error_return;
 		goto error1;
 	}
-	ITRACE(ip);
+	xfs_itrace_ref(ip);
 
 	/*
 	 * An error after we've joined dp to the transaction will result in the
@@ -3465,27 +3430,6 @@
 	goto std_return;
 }
 
-
-int
-xfs_fid2(
-	xfs_inode_t	*ip,
-	xfs_fid_t	*xfid)
-{
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
-
-	xfid->fid_len = sizeof(xfs_fid_t) - sizeof(xfid->fid_len);
-	xfid->fid_pad = 0;
-	/*
-	 * use memcpy because the inode is a long long and there's no
-	 * assurance that xfid->fid_ino is properly aligned.
-	 */
-	memcpy(&xfid->fid_ino, &ip->i_ino, sizeof(xfid->fid_ino));
-	xfid->fid_gen = ip->i_d.di_gen;
-
-	return 0;
-}
-
-
 int
 xfs_rwlock(
 	xfs_inode_t	*ip,
@@ -3558,11 +3502,11 @@
 		if (iip && iip->ili_last_lsn) {
 			xlog_t		*log = mp->m_log;
 			xfs_lsn_t	sync_lsn;
-			int		s, log_flags = XFS_LOG_FORCE;
+			int		log_flags = XFS_LOG_FORCE;
 
-			s = GRANT_LOCK(log);
+			spin_lock(&log->l_grant_lock);
 			sync_lsn = log->l_last_sync_lsn;
-			GRANT_UNLOCK(log, s);
+			spin_unlock(&log->l_grant_lock);
 
 			if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) > 0)) {
 				if (flags & FLUSH_SYNC)
@@ -3637,8 +3581,8 @@
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
-	ip->i_iocore.io_dmevmask = ip->i_d.di_dmevmask = evmask;
-	ip->i_iocore.io_dmstate  = ip->i_d.di_dmstate  = state;
+	ip->i_d.di_dmevmask = evmask;
+	ip->i_d.di_dmstate  = state;
 
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 	IHOLD(ip);
@@ -3653,7 +3597,7 @@
 {
 	bhv_vnode_t	*vp = XFS_ITOV(ip);
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	ASSERT(!VN_MAPPED(vp));
 
@@ -3871,7 +3815,7 @@
 	int			committed;
 	int			error;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -3976,7 +3920,7 @@
 		 * Issue the xfs_bmapi() call to allocate the blocks
 		 */
 		XFS_BMAP_INIT(&free_list, &firstfsb);
-		error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
+		error = xfs_bmapi(tp, ip, startoffset_fsb,
 				  allocatesize_fsb, bmapi_flag,
 				  &firstfsb, 0, imapp, &nimaps,
 				  &free_list, NULL);
@@ -4052,13 +3996,13 @@
 	int			error = 0;
 
 	bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize,
-				ip->i_d.di_flags & XFS_DIFLAG_REALTIME ?
+				XFS_IS_REALTIME_INODE(ip) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp);
 
 	for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
 		offset_fsb = XFS_B_TO_FSBT(mp, offset);
 		nimap = 1;
-		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0,
+		error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0,
 			NULL, 0, &imap, &nimap, NULL, NULL);
 		if (error || nimap < 1)
 			break;
@@ -4141,7 +4085,7 @@
 	vp = XFS_ITOV(ip);
 	mp = ip->i_mount;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
 	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
 		return error;
@@ -4149,7 +4093,7 @@
 	error = 0;
 	if (len <= 0)	/* if nothing being freed */
 		return error;
-	rt = (ip->i_d.di_flags & XFS_DIFLAG_REALTIME);
+	rt = XFS_IS_REALTIME_INODE(ip);
 	startoffset_fsb	= XFS_B_TO_FSB(mp, offset);
 	end_dmi_offset = offset + len;
 	endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
@@ -4172,15 +4116,12 @@
 		vn_iowait(ip);	/* wait for the completion of any pending DIOs */
 	}
 
-	rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP);
+	rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
 	ioffset = offset & ~(rounding - 1);
 
 	if (VN_CACHED(vp) != 0) {
-		xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
-				ctooff(offtoct(ioffset)), -1);
-		error = xfs_flushinval_pages(ip,
-				ctooff(offtoct(ioffset)),
-				-1, FI_REMAPF_LOCKED);
+		xfs_inval_cached_trace(ip, ioffset, -1, ioffset, -1);
+		error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED);
 		if (error)
 			goto out_unlock_iolock;
 	}
@@ -4193,7 +4134,7 @@
 	 */
 	if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
 		nimap = 1;
-		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb,
+		error = xfs_bmapi(NULL, ip, startoffset_fsb,
 			1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
 		if (error)
 			goto out_unlock_iolock;
@@ -4208,7 +4149,7 @@
 				startoffset_fsb += mp->m_sb.sb_rextsize - mod;
 		}
 		nimap = 1;
-		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1,
+		error = xfs_bmapi(NULL, ip, endoffset_fsb - 1,
 			1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
 		if (error)
 			goto out_unlock_iolock;
@@ -4284,7 +4225,7 @@
 		 * issue the bunmapi() call to free the blocks
 		 */
 		XFS_BMAP_INIT(&free_list, &firstfsb);
-		error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
+		error = xfs_bunmapi(tp, ip, startoffset_fsb,
 				  endoffset_fsb - startoffset_fsb,
 				  0, 2, &firstfsb, &free_list, NULL, &done);
 		if (error) {
@@ -4347,23 +4288,11 @@
 	xfs_trans_t	*tp;
 	bhv_vattr_t	va;
 
-	vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
+	xfs_itrace_entry(ip);
 
-	/*
-	 * must be a regular file and have write permission
-	 */
 	if (!S_ISREG(ip->i_d.di_mode))
 		return XFS_ERROR(EINVAL);
 
-	xfs_ilock(ip, XFS_ILOCK_SHARED);
-
-	if ((error = xfs_iaccess(ip, S_IWUSR, credp))) {
-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-		return error;
-	}
-
-	xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
 	switch (bf->l_whence) {
 	case 0: /*SEEK_SET*/
 		break;
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index b7e461c..4e3970f 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -18,7 +18,6 @@
 int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
 int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
 		struct cred *credp);
-int xfs_access(struct xfs_inode *ip, int mode, struct cred *credp);
 int xfs_readlink(struct xfs_inode *ip, char *link);
 int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
 		xfs_off_t stop);
@@ -39,7 +38,6 @@
 int xfs_symlink(struct xfs_inode *dp, bhv_vname_t *dentry,
 		char *target_path, mode_t mode, bhv_vnode_t **vpp,
 		struct cred *credp);
-int xfs_fid2(struct xfs_inode *ip, struct xfs_fid *xfid);
 int xfs_rwlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
 void xfs_rwunlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
 int xfs_inode_flush(struct xfs_inode *ip, int flags);
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index b1251b2..bbc9992 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -79,6 +79,7 @@
 extern int dmi_get_year(int field);
 extern int dmi_name_in_vendors(const char *str);
 extern int dmi_available;
+extern int dmi_walk(void (*decode)(const struct dmi_header *));
 
 #else
 
@@ -89,6 +90,8 @@
 static inline int dmi_get_year(int year) { return 0; }
 static inline int dmi_name_in_vendors(const char *s) { return 0; }
 #define dmi_available 0
+static inline int dmi_walk(void (*decode)(const struct dmi_header *))
+	{ return -1; }
 
 #endif
 
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
new file mode 100644
index 0000000..a5978f1
--- /dev/null
+++ b/include/linux/enclosure.h
@@ -0,0 +1,129 @@
+/*
+ * Enclosure Services
+ *
+ * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ *
+**-----------------------------------------------------------------------------
+**
+**  This program is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU General Public License
+**  version 2 as published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**-----------------------------------------------------------------------------
+*/
+#ifndef _LINUX_ENCLOSURE_H_
+#define _LINUX_ENCLOSURE_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+
+/* A few generic types ... taken from ses-2 */
+enum enclosure_component_type {
+	ENCLOSURE_COMPONENT_DEVICE = 0x01,
+	ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
+};
+
+/* ses-2 common element status */
+enum enclosure_status {
+	ENCLOSURE_STATUS_UNSUPPORTED = 0,
+	ENCLOSURE_STATUS_OK,
+	ENCLOSURE_STATUS_CRITICAL,
+	ENCLOSURE_STATUS_NON_CRITICAL,
+	ENCLOSURE_STATUS_UNRECOVERABLE,
+	ENCLOSURE_STATUS_NOT_INSTALLED,
+	ENCLOSURE_STATUS_UNKNOWN,
+	ENCLOSURE_STATUS_UNAVAILABLE,
+};
+
+/* SFF-8485 activity light settings */
+enum enclosure_component_setting {
+	ENCLOSURE_SETTING_DISABLED = 0,
+	ENCLOSURE_SETTING_ENABLED = 1,
+	ENCLOSURE_SETTING_BLINK_A_ON_OFF = 2,
+	ENCLOSURE_SETTING_BLINK_A_OFF_ON = 3,
+	ENCLOSURE_SETTING_BLINK_B_ON_OFF = 6,
+	ENCLOSURE_SETTING_BLINK_B_OFF_ON = 7,
+};
+
+struct enclosure_device;
+struct enclosure_component;
+struct enclosure_component_callbacks {
+	void (*get_status)(struct enclosure_device *,
+			     struct enclosure_component *);
+	int (*set_status)(struct enclosure_device *,
+			  struct enclosure_component *,
+			  enum enclosure_status);
+	void (*get_fault)(struct enclosure_device *,
+			  struct enclosure_component *);
+	int (*set_fault)(struct enclosure_device *,
+			 struct enclosure_component *,
+			 enum enclosure_component_setting);
+	void (*get_active)(struct enclosure_device *,
+			   struct enclosure_component *);
+	int (*set_active)(struct enclosure_device *,
+			  struct enclosure_component *,
+			  enum enclosure_component_setting);
+	void (*get_locate)(struct enclosure_device *,
+			   struct enclosure_component *);
+	int (*set_locate)(struct enclosure_device *,
+			  struct enclosure_component *,
+			  enum enclosure_component_setting);
+};
+
+
+struct enclosure_component {
+	void *scratch;
+	struct class_device cdev;
+	enum enclosure_component_type type;
+	int number;
+	int fault;
+	int active;
+	int locate;
+	enum enclosure_status status;
+};
+
+struct enclosure_device {
+	void *scratch;
+	struct list_head node;
+	struct class_device cdev;
+	struct enclosure_component_callbacks *cb;
+	int components;
+	struct enclosure_component component[0];
+};
+
+static inline struct enclosure_device *
+to_enclosure_device(struct class_device *dev)
+{
+	return container_of(dev, struct enclosure_device, cdev);
+}
+
+static inline struct enclosure_component *
+to_enclosure_component(struct class_device *dev)
+{
+	return container_of(dev, struct enclosure_component, cdev);
+}
+
+struct enclosure_device *
+enclosure_register(struct device *, const char *, int,
+		   struct enclosure_component_callbacks *);
+void enclosure_unregister(struct enclosure_device *);
+struct enclosure_component *
+enclosure_component_register(struct enclosure_device *, unsigned int,
+				 enum enclosure_component_type, const char *);
+int enclosure_add_device(struct enclosure_device *enclosure, int component,
+			 struct device *dev);
+int enclosure_remove_device(struct enclosure_device *enclosure, int component);
+struct enclosure_device *enclosure_find(struct device *dev);
+int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
+			      void *data);
+
+#endif /* _LINUX_ENCLOSURE_H_ */
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 8371b66..203591e 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -225,11 +225,14 @@
  * idea of the (in)accuracy of timers. Timer values are rounded up to
  * this resolution values.
  */
-# define KTIME_HIGH_RES		(ktime_t) { .tv64 = 1 }
+# define HIGH_RES_NSEC		1
+# define KTIME_HIGH_RES		(ktime_t) { .tv64 = HIGH_RES_NSEC }
+# define MONOTONIC_RES_NSEC	HIGH_RES_NSEC
 # define KTIME_MONOTONIC_RES	KTIME_HIGH_RES
 
 #else
 
+# define MONOTONIC_RES_NSEC	LOW_RES_NSEC
 # define KTIME_MONOTONIC_RES	KTIME_LOW_RES
 
 /*
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index f922b06..b979112 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -96,42 +96,6 @@
 
 #define I2C_DRIVERID_I2CDEV	900
 
-/* IDs --   Use DRIVERIDs 1000-1999 for sensors.
-   These were originally in sensors.h in the lm_sensors package */
-#define I2C_DRIVERID_LM78 1002
-#define I2C_DRIVERID_LM75 1003
-#define I2C_DRIVERID_GL518 1004
-#define I2C_DRIVERID_EEPROM 1005
-#define I2C_DRIVERID_W83781D 1006
-#define I2C_DRIVERID_LM80 1007
-#define I2C_DRIVERID_ADM1021 1008
-#define I2C_DRIVERID_ADM9240 1009
-#define I2C_DRIVERID_LTC1710 1010
-#define I2C_DRIVERID_BT869 1013
-#define I2C_DRIVERID_MAXILIFE 1014
-#define I2C_DRIVERID_MATORB 1015
-#define I2C_DRIVERID_GL520 1016
-#define I2C_DRIVERID_THMC50 1017
-#define I2C_DRIVERID_ADM1025 1020
-#define I2C_DRIVERID_LM87 1021
-#define I2C_DRIVERID_PCF8574 1022
-#define I2C_DRIVERID_MTP008 1023
-#define I2C_DRIVERID_DS1621 1024
-#define I2C_DRIVERID_ADM1024 1025
-#define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
-#define I2C_DRIVERID_FSCPOS 1028
-#define I2C_DRIVERID_FSCSCY 1029
-#define I2C_DRIVERID_PCF8591 1030
-#define I2C_DRIVERID_LM92 1033
-#define I2C_DRIVERID_SMARTBATT 1035
-#define I2C_DRIVERID_BMCSENSORS 1036
-#define I2C_DRIVERID_FS451 1037
-#define I2C_DRIVERID_LM85 1039
-#define I2C_DRIVERID_LM83 1040
-#define I2C_DRIVERID_LM90 1042
-#define I2C_DRIVERID_ASB100 1043
-#define I2C_DRIVERID_FSCHER 1046
-#define I2C_DRIVERID_W83L785TS 1047
 #define I2C_DRIVERID_OV7670 1048	/* Omnivision 7670 camera */
 
 /*
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index a6ddec1..36c542b 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -316,7 +316,8 @@
  * idea of the (in)accuracy of timers. Timer values are rounded up to
  * this resolution values.
  */
-#define KTIME_LOW_RES		(ktime_t){ .tv64 = TICK_NSEC }
+#define LOW_RES_NSEC		TICK_NSEC
+#define KTIME_LOW_RES		(ktime_t){ .tv64 = LOW_RES_NSEC }
 
 /* Get the monotonic time in timespec format: */
 extern void ktime_get_ts(struct timespec *ts);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 34023c6..bfee0bd 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -64,7 +64,10 @@
 #if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
 	    spinlock_t ptl;
 #endif
-	    struct kmem_cache *slab;	/* SLUB: Pointer to slab */
+	    struct {
+		   struct kmem_cache *slab;	/* SLUB: Pointer to slab */
+		   void *end;			/* SLUB: end marker */
+	    };
 	    struct page *first_page;	/* Compound tail pages */
 	};
 	union {
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index ddb1a70..5e6d3d6 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -11,12 +11,35 @@
 #include <linux/workqueue.h>
 #include <linux/kobject.h>
 
+enum stat_item {
+	ALLOC_FASTPATH,		/* Allocation from cpu slab */
+	ALLOC_SLOWPATH,		/* Allocation by getting a new cpu slab */
+	FREE_FASTPATH,		/* Free to cpu slub */
+	FREE_SLOWPATH,		/* Freeing not to cpu slab */
+	FREE_FROZEN,		/* Freeing to frozen slab */
+	FREE_ADD_PARTIAL,	/* Freeing moves slab to partial list */
+	FREE_REMOVE_PARTIAL,	/* Freeing removes last object */
+	ALLOC_FROM_PARTIAL,	/* Cpu slab acquired from partial list */
+	ALLOC_SLAB,		/* Cpu slab acquired from page allocator */
+	ALLOC_REFILL,		/* Refill cpu slab from slab freelist */
+	FREE_SLAB,		/* Slab freed to the page allocator */
+	CPUSLAB_FLUSH,		/* Abandoning of the cpu slab */
+	DEACTIVATE_FULL,	/* Cpu slab was full when deactivated */
+	DEACTIVATE_EMPTY,	/* Cpu slab was empty when deactivated */
+	DEACTIVATE_TO_HEAD,	/* Cpu slab was moved to the head of partials */
+	DEACTIVATE_TO_TAIL,	/* Cpu slab was moved to the tail of partials */
+	DEACTIVATE_REMOTE_FREES,/* Slab contained remotely freed objects */
+	NR_SLUB_STAT_ITEMS };
+
 struct kmem_cache_cpu {
 	void **freelist;	/* Pointer to first free per cpu object */
 	struct page *page;	/* The slab from which we are allocating */
 	int node;		/* The node of the page (or -1 for debug) */
 	unsigned int offset;	/* Freepointer offset (in word units) */
 	unsigned int objsize;	/* Size of an object (from kmem_cache) */
+#ifdef CONFIG_SLUB_STATS
+	unsigned stat[NR_SLUB_STAT_ITEMS];
+#endif
 };
 
 struct kmem_cache_node {
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 318a909..5ffec8a 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -45,8 +45,8 @@
 /* initiator tags; opaque for target */
 typedef uint32_t __bitwise__ itt_t;
 /* below makes sense only for initiator that created this tag */
-#define build_itt(itt, id, age) ((__force itt_t)\
-	((itt) | ((id) << ISCSI_CID_SHIFT) | ((age) << ISCSI_AGE_SHIFT)))
+#define build_itt(itt, age) ((__force itt_t)\
+	((itt) | ((age) << ISCSI_AGE_SHIFT)))
 #define get_itt(itt) ((__force uint32_t)(itt_t)(itt) & ISCSI_ITT_MASK)
 #define RESERVED_ITT ((__force itt_t)0xffffffff)
 
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 889f51f..7b90b63 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -70,8 +70,6 @@
 #define ISCSI_SUSPEND_BIT		1
 
 #define ISCSI_ITT_MASK			(0xfff)
-#define ISCSI_CID_SHIFT			12
-#define ISCSI_CID_MASK			(0xffff << ISCSI_CID_SHIFT)
 #define ISCSI_AGE_SHIFT			28
 #define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
 
@@ -135,6 +133,14 @@
 	return (void*)ctask->hdr + ctask->hdr_len;
 }
 
+/* Connection's states */
+enum {
+	ISCSI_CONN_INITIAL_STAGE,
+	ISCSI_CONN_STARTED,
+	ISCSI_CONN_STOPPED,
+	ISCSI_CONN_CLEANUP_WAIT,
+};
+
 struct iscsi_conn {
 	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
 	void			*dd_data;	/* iscsi_transport data */
@@ -227,6 +233,17 @@
 	int			max;		/* Max number of elements */
 };
 
+/* Session's states */
+enum {
+	ISCSI_STATE_FREE = 1,
+	ISCSI_STATE_LOGGED_IN,
+	ISCSI_STATE_FAILED,
+	ISCSI_STATE_TERMINATE,
+	ISCSI_STATE_IN_RECOVERY,
+	ISCSI_STATE_RECOVERY_FAILED,
+	ISCSI_STATE_LOGGING_OUT,
+};
+
 struct iscsi_session {
 	/*
 	 * Syncs up the scsi eh thread with the iscsi eh thread when sending
@@ -325,6 +342,10 @@
 #define session_to_cls(_sess) \
 	hostdata_session(_sess->host->hostdata)
 
+#define iscsi_session_printk(prefix, _sess, fmt, a...)	\
+	iscsi_cls_session_printk(prefix,		\
+		(struct iscsi_cls_session *)session_to_cls(_sess), fmt, ##a)
+
 /*
  * connection management
  */
@@ -339,6 +360,9 @@
 extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
 				enum iscsi_param param, char *buf);
 
+#define iscsi_conn_printk(prefix, _c, fmt, a...) \
+	iscsi_cls_conn_printk(prefix, _c->cls_conn, fmt, ##a)
+
 /*
  * pdu and task processing
  */
@@ -349,8 +373,6 @@
 				char *, uint32_t);
 extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
 			      char *, int);
-extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
-				char *, int);
 extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
 			    uint32_t *);
 extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8225157..1f74bcd 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -235,6 +235,20 @@
 #define TYPE_RBC	    0x0e
 #define TYPE_NO_LUN         0x7f
 
+/* SCSI protocols; these are taken from SPC-3 section 7.5 */
+enum scsi_protocol {
+	SCSI_PROTOCOL_FCP = 0,	/* Fibre Channel */
+	SCSI_PROTOCOL_SPI = 1,	/* parallel SCSI */
+	SCSI_PROTOCOL_SSA = 2,	/* Serial Storage Architecture - Obsolete */
+	SCSI_PROTOCOL_SBP = 3,	/* firewire */
+	SCSI_PROTOCOL_SRP = 4,	/* Infiniband RDMA */
+	SCSI_PROTOCOL_ISCSI = 5,
+	SCSI_PROTOCOL_SAS = 6,
+	SCSI_PROTOCOL_ADT = 7,	/* Media Changers */
+	SCSI_PROTOCOL_ATA = 8,
+	SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */
+};
+
 /* Returns a human-readable name for the device */
 extern const char * scsi_device_type(unsigned type);
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 5c58d59..d1299e9 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -280,39 +280,45 @@
 	 * If the host wants to be called before the scan starts, but
 	 * after the midlayer has set up ready for the scan, it can fill
 	 * in this function.
+	 *
+	 * Status: OPTIONAL
 	 */
 	void (* scan_start)(struct Scsi_Host *);
 
 	/*
-	 * fill in this function to allow the queue depth of this host
-	 * to be changeable (on a per device basis).  returns either
+	 * Fill in this function to allow the queue depth of this host
+	 * to be changeable (on a per device basis).  Returns either
 	 * the current queue depth setting (may be different from what
 	 * was passed in) or an error.  An error should only be
 	 * returned if the requested depth is legal but the driver was
 	 * unable to set it.  If the requested depth is illegal, the
 	 * driver should set and return the closest legal queue depth.
 	 *
+	 * Status: OPTIONAL
 	 */
 	int (* change_queue_depth)(struct scsi_device *, int);
 
 	/*
-	 * fill in this function to allow the changing of tag types
+	 * Fill in this function to allow the changing of tag types
 	 * (this also allows the enabling/disabling of tag command
 	 * queueing).  An error should only be returned if something
 	 * went wrong in the driver while trying to set the tag type.
 	 * If the driver doesn't support the requested tag type, then
 	 * it should set the closest type it does support without
 	 * returning an error.  Returns the actual tag type set.
+	 *
+	 * Status: OPTIONAL
 	 */
 	int (* change_queue_type)(struct scsi_device *, int);
 
 	/*
-	 * This function determines the bios parameters for a given
+	 * This function determines the BIOS parameters for a given
 	 * harddisk.  These tend to be numbers that are made up by
 	 * the host adapter.  Parameters:
 	 * size, device, list (heads, sectors, cylinders)
 	 *
-	 * Status: OPTIONAL */
+	 * Status: OPTIONAL
+	 */
 	int (* bios_param)(struct scsi_device *, struct block_device *,
 			sector_t, int []);
 
@@ -351,7 +357,7 @@
 
 	/*
 	 * This determines if we will use a non-interrupt driven
-	 * or an interrupt driven scheme,  It is set to the maximum number
+	 * or an interrupt driven scheme.  It is set to the maximum number
 	 * of simultaneous commands a given host adapter will accept.
 	 */
 	int can_queue;
@@ -372,12 +378,12 @@
 	unsigned short sg_tablesize;
 
 	/*
-	 * If the host adapter has limitations beside segment count
+	 * Set this if the host adapter has limitations beside segment count.
 	 */
 	unsigned short max_sectors;
 
 	/*
-	 * dma scatter gather segment boundary limit. a segment crossing this
+	 * DMA scatter gather segment boundary limit. A segment crossing this
 	 * boundary will be split in two.
 	 */
 	unsigned long dma_boundary;
@@ -386,7 +392,7 @@
 	 * This specifies "machine infinity" for host templates which don't
 	 * limit the transfer size.  Note this limit represents an absolute
 	 * maximum, and may be over the transfer limits allowed for
-	 * individual devices (e.g. 256 for SCSI-1)
+	 * individual devices (e.g. 256 for SCSI-1).
 	 */
 #define SCSI_DEFAULT_MAX_SECTORS	1024
 
@@ -413,12 +419,12 @@
 	unsigned supported_mode:2;
 
 	/*
-	 * true if this host adapter uses unchecked DMA onto an ISA bus.
+	 * True if this host adapter uses unchecked DMA onto an ISA bus.
 	 */
 	unsigned unchecked_isa_dma:1;
 
 	/*
-	 * true if this host adapter can make good use of clustering.
+	 * True if this host adapter can make good use of clustering.
 	 * I originally thought that if the tablesize was large that it
 	 * was a waste of CPU cycles to prepare a cluster list, but
 	 * it works out that the Buslogic is faster if you use a smaller
@@ -428,7 +434,7 @@
 	unsigned use_clustering:1;
 
 	/*
-	 * True for emulated SCSI host adapters (e.g. ATAPI)
+	 * True for emulated SCSI host adapters (e.g. ATAPI).
 	 */
 	unsigned emulated:1;
 
@@ -438,12 +444,12 @@
 	unsigned skip_settle_delay:1;
 
 	/*
-	 * ordered write support
+	 * True if we are using ordered write support.
 	 */
 	unsigned ordered_tag:1;
 
 	/*
-	 * Countdown for host blocking with no commands outstanding
+	 * Countdown for host blocking with no commands outstanding.
 	 */
 	unsigned int max_host_blocked;
 
@@ -522,8 +528,8 @@
 	struct scsi_transport_template *transportt;
 
 	/*
-	 * area to keep a shared tag map (if needed, will be
-	 * NULL if not)
+	 * Area to keep a shared tag map (if needed, will be
+	 * NULL if not).
 	 */
 	struct blk_queue_tag	*bqt;
 
@@ -596,16 +602,16 @@
 	/*
 	 * Host uses correct SCSI ordering not PC ordering. The bit is
 	 * set for the minority of drivers whose authors actually read
-	 * the spec ;)
+	 * the spec ;).
 	 */
 	unsigned reverse_ordering:1;
 
 	/*
-	 * ordered write support
+	 * Ordered write support
 	 */
 	unsigned ordered_tag:1;
 
-	/* task mgmt function in progress */
+	/* Task mgmt function in progress */
 	unsigned tmf_in_progress:1;
 
 	/* Asynchronous scan in progress */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 404f11d..dbc96ef 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -149,13 +149,6 @@
 extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 			  char *data, uint32_t data_size);
 
-
-/* Connection's states */
-#define ISCSI_CONN_INITIAL_STAGE	0
-#define ISCSI_CONN_STARTED		1
-#define ISCSI_CONN_STOPPED		2
-#define ISCSI_CONN_CLEANUP_WAIT		3
-
 struct iscsi_cls_conn {
 	struct list_head conn_list;	/* item in connlist */
 	void *dd_data;			/* LLD private data */
@@ -169,27 +162,31 @@
 #define iscsi_dev_to_conn(_dev) \
 	container_of(_dev, struct iscsi_cls_conn, dev)
 
-/* Session's states */
-#define ISCSI_STATE_FREE		1
-#define ISCSI_STATE_LOGGED_IN		2
-#define ISCSI_STATE_FAILED		3
-#define ISCSI_STATE_TERMINATE		4
-#define ISCSI_STATE_IN_RECOVERY		5
-#define ISCSI_STATE_RECOVERY_FAILED	6
-#define ISCSI_STATE_LOGGING_OUT		7
+#define iscsi_conn_to_session(_conn) \
+	iscsi_dev_to_session(_conn->dev.parent)
+
+/* iscsi class session state */
+enum {
+	ISCSI_SESSION_LOGGED_IN,
+	ISCSI_SESSION_FAILED,
+	ISCSI_SESSION_FREE,
+};
 
 struct iscsi_cls_session {
 	struct list_head sess_list;		/* item in session_list */
 	struct list_head host_list;
 	struct iscsi_transport *transport;
+	spinlock_t lock;
+	struct work_struct scan_work;
+	struct work_struct unbind_work;
 
 	/* recovery fields */
 	int recovery_tmo;
 	struct delayed_work recovery_work;
-	struct work_struct unbind_work;
 
 	int target_id;
 
+	int state;
 	int sid;				/* session id */
 	void *dd_data;				/* LLD private data */
 	struct device dev;	/* sysfs transport/container device */
@@ -206,14 +203,22 @@
 
 struct iscsi_host {
 	struct list_head sessions;
+	atomic_t nr_scans;
 	struct mutex mutex;
-	struct workqueue_struct *unbind_workq;
-	char unbind_workq_name[KOBJ_NAME_LEN];
+	struct workqueue_struct *scan_workq;
+	char scan_workq_name[KOBJ_NAME_LEN];
 };
 
 /*
  * session and connection functions that can be used by HW iSCSI LLDs
  */
+#define iscsi_cls_session_printk(prefix, _cls_session, fmt, a...) \
+	dev_printk(prefix, &(_cls_session)->dev, fmt, ##a)
+
+#define iscsi_cls_conn_printk(prefix, _cls_conn, fmt, a...) \
+	dev_printk(prefix, &(_cls_conn)->dev, fmt, ##a)
+
+extern int iscsi_session_chkready(struct iscsi_cls_session *session);
 extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
 					struct iscsi_transport *transport);
 extern int iscsi_add_session(struct iscsi_cls_session *session,
@@ -231,6 +236,6 @@
 extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
 extern void iscsi_unblock_session(struct iscsi_cls_session *session);
 extern void iscsi_block_session(struct iscsi_cls_session *session);
-
+extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
 
 #endif
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 0d385be..4f4008f 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -205,6 +205,19 @@
 	  off in a kernel built with CONFIG_SLUB_DEBUG_ON by specifying
 	  "slub_debug=-".
 
+config SLUB_STATS
+	default n
+	bool "Enable SLUB performance statistics"
+	depends on SLUB
+	help
+	  SLUB statistics are useful to debug SLUBs allocation behavior in
+	  order find ways to optimize the allocator. This should never be
+	  enabled for production use since keeping statistics slows down
+	  the allocator by a few percentage points. The slabinfo command
+	  supports the determination of the most active slabs to figure
+	  out which slabs are relevant to a particular load.
+	  Try running: slabinfo -DA
+
 config DEBUG_PREEMPT
 	bool "Debug preemptible kernel"
 	depends on DEBUG_KERNEL && PREEMPT && (TRACE_IRQFLAGS_SUPPORT || PPC64)
diff --git a/mm/slub.c b/mm/slub.c
index 3f05667..e2989ae 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -149,6 +149,13 @@
 /* Enable to test recovery from slab corruption on boot */
 #undef SLUB_RESILIENCY_TEST
 
+/*
+ * Currently fastpath is not supported if preemption is enabled.
+ */
+#if defined(CONFIG_FAST_CMPXCHG_LOCAL) && !defined(CONFIG_PREEMPT)
+#define SLUB_FASTPATH
+#endif
+
 #if PAGE_SHIFT <= 12
 
 /*
@@ -243,6 +250,7 @@
 static int sysfs_slab_add(struct kmem_cache *);
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
 static void sysfs_slab_remove(struct kmem_cache *);
+
 #else
 static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
 static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
@@ -251,8 +259,16 @@
 {
 	kfree(s);
 }
+
 #endif
 
+static inline void stat(struct kmem_cache_cpu *c, enum stat_item si)
+{
+#ifdef CONFIG_SLUB_STATS
+	c->stat[si]++;
+#endif
+}
+
 /********************************************************************
  * 			Core slab cache functions
  *******************************************************************/
@@ -280,15 +296,32 @@
 #endif
 }
 
+/*
+ * The end pointer in a slab is special. It points to the first object in the
+ * slab but has bit 0 set to mark it.
+ *
+ * Note that SLUB relies on page_mapping returning NULL for pages with bit 0
+ * in the mapping set.
+ */
+static inline int is_end(void *addr)
+{
+	return (unsigned long)addr & PAGE_MAPPING_ANON;
+}
+
+void *slab_address(struct page *page)
+{
+	return page->end - PAGE_MAPPING_ANON;
+}
+
 static inline int check_valid_pointer(struct kmem_cache *s,
 				struct page *page, const void *object)
 {
 	void *base;
 
-	if (!object)
+	if (object == page->end)
 		return 1;
 
-	base = page_address(page);
+	base = slab_address(page);
 	if (object < base || object >= base + s->objects * s->size ||
 		(object - base) % s->size) {
 		return 0;
@@ -321,7 +354,8 @@
 
 /* Scan freelist */
 #define for_each_free_object(__p, __s, __free) \
-	for (__p = (__free); __p; __p = get_freepointer((__s), __p))
+	for (__p = (__free); (__p) != page->end; __p = get_freepointer((__s),\
+		__p))
 
 /* Determine object index from a given position */
 static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
@@ -473,7 +507,7 @@
 static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
 {
 	unsigned int off;	/* Offset of last byte */
-	u8 *addr = page_address(page);
+	u8 *addr = slab_address(page);
 
 	print_tracking(s, p);
 
@@ -651,7 +685,7 @@
 	if (!(s->flags & SLAB_POISON))
 		return 1;
 
-	start = page_address(page);
+	start = slab_address(page);
 	end = start + (PAGE_SIZE << s->order);
 	length = s->objects * s->size;
 	remainder = end - (start + length);
@@ -685,9 +719,10 @@
 			endobject, red, s->inuse - s->objsize))
 			return 0;
 	} else {
-		if ((s->flags & SLAB_POISON) && s->objsize < s->inuse)
-			check_bytes_and_report(s, page, p, "Alignment padding", endobject,
-				POISON_INUSE, s->inuse - s->objsize);
+		if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) {
+			check_bytes_and_report(s, page, p, "Alignment padding",
+				endobject, POISON_INUSE, s->inuse - s->objsize);
+		}
 	}
 
 	if (s->flags & SLAB_POISON) {
@@ -718,7 +753,7 @@
 		 * of the free objects in this slab. May cause
 		 * another error because the object count is now wrong.
 		 */
-		set_freepointer(s, p, NULL);
+		set_freepointer(s, p, page->end);
 		return 0;
 	}
 	return 1;
@@ -752,18 +787,18 @@
 	void *fp = page->freelist;
 	void *object = NULL;
 
-	while (fp && nr <= s->objects) {
+	while (fp != page->end && nr <= s->objects) {
 		if (fp == search)
 			return 1;
 		if (!check_valid_pointer(s, page, fp)) {
 			if (object) {
 				object_err(s, page, object,
 					"Freechain corrupt");
-				set_freepointer(s, object, NULL);
+				set_freepointer(s, object, page->end);
 				break;
 			} else {
 				slab_err(s, page, "Freepointer corrupt");
-				page->freelist = NULL;
+				page->freelist = page->end;
 				page->inuse = s->objects;
 				slab_fix(s, "Freelist cleared");
 				return 0;
@@ -869,7 +904,7 @@
 		 */
 		slab_fix(s, "Marking all objects used");
 		page->inuse = s->objects;
-		page->freelist = NULL;
+		page->freelist = page->end;
 	}
 	return 0;
 }
@@ -894,11 +929,10 @@
 		return 0;
 
 	if (unlikely(s != page->slab)) {
-		if (!PageSlab(page))
+		if (!PageSlab(page)) {
 			slab_err(s, page, "Attempt to free object(0x%p) "
 				"outside of slab", object);
-		else
-		if (!page->slab) {
+		} else if (!page->slab) {
 			printk(KERN_ERR
 				"SLUB <none>: no slab for object 0x%p.\n",
 						object);
@@ -910,7 +944,7 @@
 	}
 
 	/* Special debug activities for freeing objects */
-	if (!SlabFrozen(page) && !page->freelist)
+	if (!SlabFrozen(page) && page->freelist == page->end)
 		remove_full(s, page);
 	if (s->flags & SLAB_STORE_USER)
 		set_track(s, object, TRACK_FREE, addr);
@@ -1007,7 +1041,7 @@
 		 */
 		if (slub_debug && (!slub_debug_slabs ||
 		    strncmp(slub_debug_slabs, name,
-		    	strlen(slub_debug_slabs)) == 0))
+			strlen(slub_debug_slabs)) == 0))
 				flags |= slub_debug;
 	}
 
@@ -1102,6 +1136,7 @@
 		SetSlabDebug(page);
 
 	start = page_address(page);
+	page->end = start + 1;
 
 	if (unlikely(s->flags & SLAB_POISON))
 		memset(start, POISON_INUSE, PAGE_SIZE << s->order);
@@ -1113,7 +1148,7 @@
 		last = p;
 	}
 	setup_object(s, page, last);
-	set_freepointer(s, last, NULL);
+	set_freepointer(s, last, page->end);
 
 	page->freelist = start;
 	page->inuse = 0;
@@ -1129,7 +1164,7 @@
 		void *p;
 
 		slab_pad_check(s, page);
-		for_each_object(p, s, page_address(page))
+		for_each_object(p, s, slab_address(page))
 			check_object(s, page, p, 0);
 		ClearSlabDebug(page);
 	}
@@ -1139,6 +1174,7 @@
 		NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
 		-pages);
 
+	page->mapping = NULL;
 	__free_pages(page, s->order);
 }
 
@@ -1183,7 +1219,7 @@
 
 static __always_inline void slab_unlock(struct page *page)
 {
-	bit_spin_unlock(PG_locked, &page->flags);
+	__bit_spin_unlock(PG_locked, &page->flags);
 }
 
 static __always_inline int slab_trylock(struct page *page)
@@ -1294,8 +1330,8 @@
 			get_cycles() % 1024 > s->remote_node_defrag_ratio)
 		return NULL;
 
-	zonelist = &NODE_DATA(slab_node(current->mempolicy))
-					->node_zonelists[gfp_zone(flags)];
+	zonelist = &NODE_DATA(
+		slab_node(current->mempolicy))->node_zonelists[gfp_zone(flags)];
 	for (z = zonelist->zones; *z; z++) {
 		struct kmem_cache_node *n;
 
@@ -1337,17 +1373,22 @@
 static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
 {
 	struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+	struct kmem_cache_cpu *c = get_cpu_slab(s, smp_processor_id());
 
 	ClearSlabFrozen(page);
 	if (page->inuse) {
 
-		if (page->freelist)
+		if (page->freelist != page->end) {
 			add_partial(n, page, tail);
-		else if (SlabDebug(page) && (s->flags & SLAB_STORE_USER))
-			add_full(n, page);
+			stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
+		} else {
+			stat(c, DEACTIVATE_FULL);
+			if (SlabDebug(page) && (s->flags & SLAB_STORE_USER))
+				add_full(n, page);
+		}
 		slab_unlock(page);
-
 	} else {
+		stat(c, DEACTIVATE_EMPTY);
 		if (n->nr_partial < MIN_PARTIAL) {
 			/*
 			 * Adding an empty slab to the partial slabs in order
@@ -1361,6 +1402,7 @@
 			slab_unlock(page);
 		} else {
 			slab_unlock(page);
+			stat(get_cpu_slab(s, raw_smp_processor_id()), FREE_SLAB);
 			discard_slab(s, page);
 		}
 	}
@@ -1373,12 +1415,19 @@
 {
 	struct page *page = c->page;
 	int tail = 1;
+
+	if (c->freelist)
+		stat(c, DEACTIVATE_REMOTE_FREES);
 	/*
 	 * Merge cpu freelist into freelist. Typically we get here
 	 * because both freelists are empty. So this is unlikely
 	 * to occur.
+	 *
+	 * We need to use _is_end here because deactivate slab may
+	 * be called for a debug slab. Then c->freelist may contain
+	 * a dummy pointer.
 	 */
-	while (unlikely(c->freelist)) {
+	while (unlikely(!is_end(c->freelist))) {
 		void **object;
 
 		tail = 0;	/* Hot objects. Put the slab first */
@@ -1398,6 +1447,7 @@
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 {
+	stat(c, CPUSLAB_FLUSH);
 	slab_lock(c->page);
 	deactivate_slab(s, c);
 }
@@ -1469,16 +1519,21 @@
 {
 	void **object;
 	struct page *new;
+#ifdef SLUB_FASTPATH
+	unsigned long flags;
 
+	local_irq_save(flags);
+#endif
 	if (!c->page)
 		goto new_slab;
 
 	slab_lock(c->page);
 	if (unlikely(!node_match(c, node)))
 		goto another_slab;
+	stat(c, ALLOC_REFILL);
 load_freelist:
 	object = c->page->freelist;
-	if (unlikely(!object))
+	if (unlikely(object == c->page->end))
 		goto another_slab;
 	if (unlikely(SlabDebug(c->page)))
 		goto debug;
@@ -1486,9 +1541,15 @@
 	object = c->page->freelist;
 	c->freelist = object[c->offset];
 	c->page->inuse = s->objects;
-	c->page->freelist = NULL;
+	c->page->freelist = c->page->end;
 	c->node = page_to_nid(c->page);
+unlock_out:
 	slab_unlock(c->page);
+	stat(c, ALLOC_SLOWPATH);
+out:
+#ifdef SLUB_FASTPATH
+	local_irq_restore(flags);
+#endif
 	return object;
 
 another_slab:
@@ -1498,6 +1559,7 @@
 	new = get_partial(s, gfpflags, node);
 	if (new) {
 		c->page = new;
+		stat(c, ALLOC_FROM_PARTIAL);
 		goto load_freelist;
 	}
 
@@ -1511,6 +1573,7 @@
 
 	if (new) {
 		c = get_cpu_slab(s, smp_processor_id());
+		stat(c, ALLOC_SLAB);
 		if (c->page)
 			flush_slab(s, c);
 		slab_lock(new);
@@ -1518,7 +1581,8 @@
 		c->page = new;
 		goto load_freelist;
 	}
-	return NULL;
+	object = NULL;
+	goto out;
 debug:
 	object = c->page->freelist;
 	if (!alloc_debug_processing(s, c->page, object, addr))
@@ -1527,8 +1591,7 @@
 	c->page->inuse++;
 	c->page->freelist = object[c->offset];
 	c->node = -1;
-	slab_unlock(c->page);
-	return object;
+	goto unlock_out;
 }
 
 /*
@@ -1545,20 +1608,50 @@
 		gfp_t gfpflags, int node, void *addr)
 {
 	void **object;
-	unsigned long flags;
 	struct kmem_cache_cpu *c;
 
+/*
+ * The SLUB_FASTPATH path is provisional and is currently disabled if the
+ * kernel is compiled with preemption or if the arch does not support
+ * fast cmpxchg operations. There are a couple of coming changes that will
+ * simplify matters and allow preemption. Ultimately we may end up making
+ * SLUB_FASTPATH the default.
+ *
+ * 1. The introduction of the per cpu allocator will avoid array lookups
+ *    through get_cpu_slab(). A special register can be used instead.
+ *
+ * 2. The introduction of per cpu atomic operations (cpu_ops) means that
+ *    we can realize the logic here entirely with per cpu atomics. The
+ *    per cpu atomic ops will take care of the preemption issues.
+ */
+
+#ifdef SLUB_FASTPATH
+	c = get_cpu_slab(s, raw_smp_processor_id());
+	do {
+		object = c->freelist;
+		if (unlikely(is_end(object) || !node_match(c, node))) {
+			object = __slab_alloc(s, gfpflags, node, addr, c);
+			break;
+		}
+		stat(c, ALLOC_FASTPATH);
+	} while (cmpxchg_local(&c->freelist, object, object[c->offset])
+								!= object);
+#else
+	unsigned long flags;
+
 	local_irq_save(flags);
 	c = get_cpu_slab(s, smp_processor_id());
-	if (unlikely(!c->freelist || !node_match(c, node)))
+	if (unlikely(is_end(c->freelist) || !node_match(c, node)))
 
 		object = __slab_alloc(s, gfpflags, node, addr, c);
 
 	else {
 		object = c->freelist;
 		c->freelist = object[c->offset];
+		stat(c, ALLOC_FASTPATH);
 	}
 	local_irq_restore(flags);
+#endif
 
 	if (unlikely((gfpflags & __GFP_ZERO) && object))
 		memset(object, 0, c->objsize);
@@ -1593,7 +1686,15 @@
 {
 	void *prior;
 	void **object = (void *)x;
+	struct kmem_cache_cpu *c;
 
+#ifdef SLUB_FASTPATH
+	unsigned long flags;
+
+	local_irq_save(flags);
+#endif
+	c = get_cpu_slab(s, raw_smp_processor_id());
+	stat(c, FREE_SLOWPATH);
 	slab_lock(page);
 
 	if (unlikely(SlabDebug(page)))
@@ -1603,8 +1704,10 @@
 	page->freelist = object;
 	page->inuse--;
 
-	if (unlikely(SlabFrozen(page)))
+	if (unlikely(SlabFrozen(page))) {
+		stat(c, FREE_FROZEN);
 		goto out_unlock;
+	}
 
 	if (unlikely(!page->inuse))
 		goto slab_empty;
@@ -1614,21 +1717,31 @@
 	 * was not on the partial list before
 	 * then add it.
 	 */
-	if (unlikely(!prior))
+	if (unlikely(prior == page->end)) {
 		add_partial(get_node(s, page_to_nid(page)), page, 1);
+		stat(c, FREE_ADD_PARTIAL);
+	}
 
 out_unlock:
 	slab_unlock(page);
+#ifdef SLUB_FASTPATH
+	local_irq_restore(flags);
+#endif
 	return;
 
 slab_empty:
-	if (prior)
+	if (prior != page->end) {
 		/*
 		 * Slab still on the partial list.
 		 */
 		remove_partial(s, page);
-
+		stat(c, FREE_REMOVE_PARTIAL);
+	}
 	slab_unlock(page);
+	stat(c, FREE_SLAB);
+#ifdef SLUB_FASTPATH
+	local_irq_restore(flags);
+#endif
 	discard_slab(s, page);
 	return;
 
@@ -1653,19 +1766,49 @@
 			struct page *page, void *x, void *addr)
 {
 	void **object = (void *)x;
-	unsigned long flags;
 	struct kmem_cache_cpu *c;
 
+#ifdef SLUB_FASTPATH
+	void **freelist;
+
+	c = get_cpu_slab(s, raw_smp_processor_id());
+	debug_check_no_locks_freed(object, s->objsize);
+	do {
+		freelist = c->freelist;
+		barrier();
+		/*
+		 * If the compiler would reorder the retrieval of c->page to
+		 * come before c->freelist then an interrupt could
+		 * change the cpu slab before we retrieve c->freelist. We
+		 * could be matching on a page no longer active and put the
+		 * object onto the freelist of the wrong slab.
+		 *
+		 * On the other hand: If we already have the freelist pointer
+		 * then any change of cpu_slab will cause the cmpxchg to fail
+		 * since the freelist pointers are unique per slab.
+		 */
+		if (unlikely(page != c->page || c->node < 0)) {
+			__slab_free(s, page, x, addr, c->offset);
+			break;
+		}
+		object[c->offset] = freelist;
+		stat(c, FREE_FASTPATH);
+	} while (cmpxchg_local(&c->freelist, freelist, object) != freelist);
+#else
+	unsigned long flags;
+
 	local_irq_save(flags);
 	debug_check_no_locks_freed(object, s->objsize);
 	c = get_cpu_slab(s, smp_processor_id());
 	if (likely(page == c->page && c->node >= 0)) {
 		object[c->offset] = c->freelist;
 		c->freelist = object;
+		stat(c, FREE_FASTPATH);
 	} else
 		__slab_free(s, page, x, addr, c->offset);
 
 	local_irq_restore(flags);
+#endif
 }
 
 void kmem_cache_free(struct kmem_cache *s, void *x)
@@ -1842,7 +1985,7 @@
 			struct kmem_cache_cpu *c)
 {
 	c->page = NULL;
-	c->freelist = NULL;
+	c->freelist = (void *)PAGE_MAPPING_ANON;
 	c->node = 0;
 	c->offset = s->offset / sizeof(void *);
 	c->objsize = s->objsize;
@@ -2446,7 +2589,8 @@
 		goto unlock_out;
 
 	realsize = kmalloc_caches[index].objsize;
-	text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d", (unsigned int)realsize),
+	text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
+			 (unsigned int)realsize);
 	s = kmalloc(kmem_size, flags & ~SLUB_DMA);
 
 	if (!s || !text || !kmem_cache_open(s, flags, text,
@@ -2601,6 +2745,7 @@
 void kfree(const void *x)
 {
 	struct page *page;
+	void *object = (void *)x;
 
 	if (unlikely(ZERO_OR_NULL_PTR(x)))
 		return;
@@ -2610,7 +2755,7 @@
 		put_page(page);
 		return;
 	}
-	slab_free(page->slab, page, (void *)x, __builtin_return_address(0));
+	slab_free(page->slab, page, object, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(kfree);
 
@@ -2896,7 +3041,8 @@
 #endif
 
 
-	printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
+	printk(KERN_INFO
+		"SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
 		" CPUs=%d, Nodes=%d\n",
 		caches, cache_line_size(),
 		slub_min_order, slub_max_order, slub_min_objects,
@@ -3063,7 +3209,7 @@
 }
 
 static struct notifier_block __cpuinitdata slab_notifier = {
-	&slab_cpuup_callback, NULL, 0
+	.notifier_call = slab_cpuup_callback
 };
 
 #endif
@@ -3104,7 +3250,7 @@
 						unsigned long *map)
 {
 	void *p;
-	void *addr = page_address(page);
+	void *addr = slab_address(page);
 
 	if (!check_slab(s, page) ||
 			!on_freelist(s, page, NULL))
@@ -3221,8 +3367,9 @@
 	p = kzalloc(32, GFP_KERNEL);
 	p[32 + sizeof(void *)] = 0x34;
 	printk(KERN_ERR "\n2. kmalloc-32: Clobber next pointer/next slab"
-		 	" 0x34 -> -0x%p\n", p);
-	printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
+			" 0x34 -> -0x%p\n", p);
+	printk(KERN_ERR
+		"If allocated object is overwritten then not detectable\n\n");
 
 	validate_slab_cache(kmalloc_caches + 5);
 	p = kzalloc(64, GFP_KERNEL);
@@ -3230,7 +3377,8 @@
 	*p = 0x56;
 	printk(KERN_ERR "\n3. kmalloc-64: corrupting random byte 0x56->0x%p\n",
 									p);
-	printk(KERN_ERR "If allocated object is overwritten then not detectable\n\n");
+	printk(KERN_ERR
+		"If allocated object is overwritten then not detectable\n\n");
 	validate_slab_cache(kmalloc_caches + 6);
 
 	printk(KERN_ERR "\nB. Corruption after free\n");
@@ -3243,7 +3391,8 @@
 	p = kzalloc(256, GFP_KERNEL);
 	kfree(p);
 	p[50] = 0x9a;
-	printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n", p);
+	printk(KERN_ERR "\n2. kmalloc-256: Clobber 50th byte 0x9a->0x%p\n\n",
+			p);
 	validate_slab_cache(kmalloc_caches + 8);
 
 	p = kzalloc(512, GFP_KERNEL);
@@ -3384,7 +3533,7 @@
 static void process_slab(struct loc_track *t, struct kmem_cache *s,
 		struct page *page, enum track_item alloc)
 {
-	void *addr = page_address(page);
+	void *addr = slab_address(page);
 	DECLARE_BITMAP(map, s->objects);
 	void *p;
 
@@ -3872,6 +4021,62 @@
 SLAB_ATTR(remote_node_defrag_ratio);
 #endif
 
+#ifdef CONFIG_SLUB_STATS
+
+static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si)
+{
+	unsigned long sum  = 0;
+	int cpu;
+	int len;
+	int *data = kmalloc(nr_cpu_ids * sizeof(int), GFP_KERNEL);
+
+	if (!data)
+		return -ENOMEM;
+
+	for_each_online_cpu(cpu) {
+		unsigned x = get_cpu_slab(s, cpu)->stat[si];
+
+		data[cpu] = x;
+		sum += x;
+	}
+
+	len = sprintf(buf, "%lu", sum);
+
+	for_each_online_cpu(cpu) {
+		if (data[cpu] && len < PAGE_SIZE - 20)
+			len += sprintf(buf + len, " c%d=%u", cpu, data[cpu]);
+	}
+	kfree(data);
+	return len + sprintf(buf + len, "\n");
+}
+
+#define STAT_ATTR(si, text) 					\
+static ssize_t text##_show(struct kmem_cache *s, char *buf)	\
+{								\
+	return show_stat(s, buf, si);				\
+}								\
+SLAB_ATTR_RO(text);						\
+
+STAT_ATTR(ALLOC_FASTPATH, alloc_fastpath);
+STAT_ATTR(ALLOC_SLOWPATH, alloc_slowpath);
+STAT_ATTR(FREE_FASTPATH, free_fastpath);
+STAT_ATTR(FREE_SLOWPATH, free_slowpath);
+STAT_ATTR(FREE_FROZEN, free_frozen);
+STAT_ATTR(FREE_ADD_PARTIAL, free_add_partial);
+STAT_ATTR(FREE_REMOVE_PARTIAL, free_remove_partial);
+STAT_ATTR(ALLOC_FROM_PARTIAL, alloc_from_partial);
+STAT_ATTR(ALLOC_SLAB, alloc_slab);
+STAT_ATTR(ALLOC_REFILL, alloc_refill);
+STAT_ATTR(FREE_SLAB, free_slab);
+STAT_ATTR(CPUSLAB_FLUSH, cpuslab_flush);
+STAT_ATTR(DEACTIVATE_FULL, deactivate_full);
+STAT_ATTR(DEACTIVATE_EMPTY, deactivate_empty);
+STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate_to_head);
+STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail);
+STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees);
+
+#endif
+
 static struct attribute *slab_attrs[] = {
 	&slab_size_attr.attr,
 	&object_size_attr.attr,
@@ -3902,6 +4107,25 @@
 #ifdef CONFIG_NUMA
 	&remote_node_defrag_ratio_attr.attr,
 #endif
+#ifdef CONFIG_SLUB_STATS
+	&alloc_fastpath_attr.attr,
+	&alloc_slowpath_attr.attr,
+	&free_fastpath_attr.attr,
+	&free_slowpath_attr.attr,
+	&free_frozen_attr.attr,
+	&free_add_partial_attr.attr,
+	&free_remove_partial_attr.attr,
+	&alloc_from_partial_attr.attr,
+	&alloc_slab_attr.attr,
+	&alloc_refill_attr.attr,
+	&free_slab_attr.attr,
+	&cpuslab_flush_attr.attr,
+	&deactivate_full_attr.attr,
+	&deactivate_empty_attr.attr,
+	&deactivate_to_head_attr.attr,
+	&deactivate_to_tail_attr.attr,
+	&deactivate_remote_frees_attr.attr,
+#endif
 	NULL
 };